Posts tagged ‘io thread’

mysql show slave status

 



1. 概览

做了一个列表,简单注释了一下各个字段的意思,如下:

字段名 注释 可能取值 取值示例
Slave_IO_State slave状态的文字描述 slave线程状态 Waiting for master to send event
Master_Host master的IP或主机名 172.20.164.67
Master_User 连接master使用的用户名 repl
Master_Port 连接master使用的密码 3306
Connect_Retry 重新连接MySQL的重试间隔时间,单位秒 60
Master_Log_File IO thread读取到的binlog日志文件 Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置 mysql-bin.001896
Read_Master_Log_Pos IO thread读取到的binlog日志文件位置 226029100
Relay_Log_File slave 在本地缓存的relay 日志的文件名 mysql-relay-bin.002014
Relay_Log_Pos slave 在本地缓存的relay 日志的文件位置 87341525
Relay_Master_Log_File SQL thread 执行到master的binlog文件名 mysql-bin.001896
Slave_IO_Running IO thread是否正常运行 Yes
Slave_SQL_Running SQL thread是否正常运行 Yes
Replicate_Do_DB slave上需要执行的schema
Replicate_Ignore_DB slave上需要忽略的schema
Replicate_Do_Table slave上需要执行的table
Replicate_Ignore_Table slave上需要忽略的table
Replicate_Wild_Do_Table slave上需要执行的table正则表达式
Replicate_Wild_Ignore_Table slave上需要忽略的table正则表达式
Last_Errno 上一次出错的错误号 0
Last_Error 上一次出错的错误信息
Skip_Counter 还剩下的忽略event次数 0
Exec_Master_Log_Pos SQL thread 执行到master的binlog文件位置 226029100
Relay_Log_Space relay log占用的空间大小 87341723
Until_Condition 复制until条件,在stop slave,start slave(不带until)或server重启的时候会自动重置 None
Until_Log_File 复制停止的文件名
Until_Log_Pos 复制停止的文件位置 0
Master_SSL_Allowed 是否使用SSL连接master No
Master_SSL_CA_File ssl agent文件ca-cert.pem的文件名 /etc/mysql/newcerts/ca-cert.pem
Master_SSL_CA_Path ssl agent文件ca-cert.pem的路径名
Master_SSL_Cert ssl 授权文件 /etc/mysql/newcerts/client-cert.pem
Master_SSL_Cipher ssl 加密算法
Master_SSL_Key ssl 密钥文件 /etc/mysql/newcerts/client-key.pem
Seconds_Behind_Master SQL thread相对master的延迟时间 0
Master_SSL_Verify_Server_Cert 是否检查master的授权文件 No
Last_IO_Errno IO thread的上一次出错的错误号 0
Last_IO_Error IO thread的上一次出错的错误信息
Last_SQL_Errno SQL thread的上一次出错的错误号 0
Last_SQL_Error SQL thread的上一次出错的错误信息

  • IO thread, SQL thread状态变更
  • Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置
  • Replicate_Do, Replicate_Ignore 讨论
  • mysql ssl连接
  • replication文件 master.info, relay.info和连接信息解析
  • Seconds_Behind_Master 精确性
  • replication until和复制延迟控制
  • skip counter忽略event计数和精确性本文只涉及第一和第二个议题

2. IO thread, SQL thread状态变更

  1. IO线程状态变更,对应show slave status的Slave_IO_State字段
名称 状态值 解释
wait_master Waiting for master update
connect_master Connecting to master
check_master Checking master version
register_slave Registering slave on master
request_binlog Requesting binlog dump
request_wait_reconnect Waiting to reconnect after a failed binlog dump request
request_reconnecting Reconnecting after a failed binlog dump request
wait_event Waiting for master to send event
queue_to_relay_log Queueing master event to the relay log
read_wait_reconnect Waiting to reconnect after a failed master event read
read_reconnecting Reconnecting after a failed master event read
wait_relay_space Waiting for the slave SQL thread to free enough relay log space
wait_slave_mutex Waiting for slave mutex on exit

状态变更图如下:
io_thread 状态变更
代码请参考sql/slave.cc的handle_slave_io函数

  1. SQL线程状态变更,对应服务器上SQL线程的State字段,通过show processlist查看
名称 状态值 解释
wait_relay_event Waiting for the next event in relay log
read_relay Reading event from the relay log
wait_io_thread Has read all relay log; waiting for the slave I/O thread to update it
make_temp_file Making temp file
wait_slave_mutex Waiting for slave mutex on exit

状态变更图如下:

sql_thread 状态变更

代码请参考sql/slave.cc的handle_slave_sql函数

3. Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置

  1. 定义
  • Master_Log_File,Read_Master_Log_Pos 记录了IO thread读到的当前master binlog文件和位置,对应master的binlog文件和位置。
  • Relay_Log_File,Relay_Log_Pos记录了SQL thread执行到relay log的那个文件和位置,对应的是slave上的relay log文件和位置。
  • Relay_Master_Log_File,Exec_Master_Log_Pos记录的是SQL thread执行到master binlog的文件和位置,对应的master上binlog的文件和位置。
  1. 日志文件介绍需要明确这几个值的意思,我们首先需要了解binlog日志文件和relay log日志文件的具体结构。binlog的文件格式可以参考 Mats Kindah和Lars Thalman的binlog API文档。binlog的event可以参考我之前的blog和binlog events 介绍
    • binlog数据文件示例binlog文件和relay log文件都可以用mysqlbinlg工具来打开。下图是一个mysqlbinlog解析普通的binlog文件出来的文本文件:我们这里主要是row方式的binlog。

      注意:binlog的event语句开始位置就是二进制binlog文件的字节偏移位置。而且根据上一个event的end_log_pos可以找到下一个event开始的位置,如上图所示。

  • relay log数据文件示例binlog文件和relay log文件都可以用mysqlbinlg工具来打开。下图是一个mysqlbinlog解析普通的relay log文件出来的文本文件:relay log和binlog记录方式基本相同,最大的不同就是end_log_pos记录的是master的binlog文件中event的位置,而不是relay log自己event的位置。如图所示,上一个event的end_log_pos和下一个relay log event开始的位置不一样。

为什么需要这样设置?原因很简单,就是为了方便找到master binlog的位置,在slave上,记录relay log 下一个event的开始偏移意义不大,但是如果记录了master binlog的偏移量,我们就可以在SQL thread中明确我们执行到master的某个binlog的哪个位置了。那么是哪个binlog列。我们找到relay log的最前面。

如图所示,每个relay log开头都有这么一个rotate event,也就是当前master的binlog文件名。引用一下Automated master failover的一页PPT如下。

这里列出了Read_Master_Log_Pos,Relay_Log_Pos,Exec_Master_Log_Pos 的具体位置。

  • IO thread 把所有从master读到的binlog记录到本地的binlog中,所以relay log的最后一个event的end log_pos就是Read_Master_Log_Pos
  • SQL thread 按照transaction来执行,所以Exec_Master_Log_Pos对应relay log中最后一个事务event的end_log_pos,这个位置对应的是master的binlog的位置。
  • Relay_Log_Pos 记录的是SQL thread执行的event在relay log中结束位置,这个才是relay log的偏移量。

4. 参考资料

mysql reference IO 线程状态

mysql reference SQL 线程状态

mysql reference show slave status

binlog events

binlog API

Automated master failover


双slave的server_id相同的问题

前段时间新来了一个机器,想要替换一个应用的备机。
已有的架构是这样的:A和B两个MySQL相互作为备机,A的性能比较好,B的性能比较差。
现在买了一台新的机器,新的机器c性能比较好,准备用来替换B。
安装MySQL和配置等等都不细说,比较顺利的。

但是安装好以后,配置复制的时候出现了问题,change master以后可以复制,但是数据库监控一直报错。
show slave status\G显示的Seconds_Behind_Master:的复制延迟一下子是0,一下子是90多w秒。
以前我们也遇到过类似的问题,具体原因不大记得了(唉,就是没有文档记录的错阿),最后好像是通过重做复制修复了。
尝试重新change master以后还是没有好转。查看错误日志显示如下:
100817 19:45:45 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘mysql-bin.000033’ at postion 271148235
100817 19:45:45 [Note] Slave: received end packet from server, apparent master shutdown:
100817 19:45:45 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘mysql-bin.000033’ at postion 271148235
100817 19:45:45 [Note] Slave: received end packet from server, apparent master shutdown:
并且不断的在刷,每秒钟有十来条记录。
通过对应的binlog file和binlog position去查看主机对应的记录都没有问题。并且主机到备机的复制只是时断时续,并没有一直停着不往前走。
实在没有办法,最后停掉了复制。这个事情因为并不是那么紧急,所以也暂时放在一边了。

偶尔的机会,我在备机B上也发现了同样的错误,也是Slave: received end packet from server, apparent master shutdown的错误。
并且change master以后,出现的频率变的非常高。
看了一下my.cnf配置文件,注意到B和C配置的server_id都是2,因为C当时是计划替换B的所以server_id也配置为一样了。
是不是这个问题引起的列?试试就知道了,把C的server_id配置成3,数据库B和数据库C检查复制状态,好了!

想起数据库复制的那一块代码。数据库连接master,请求复制开始的时候需要几个参数:
1、四个字节的数据文件开始位置
2、两个字节的binlog flag(目前还没有用上)
3、2个字节的binlog file名字字符串长度
4、4个字节的server_id
5、n个字节的binlog file名字字符串(在前面3里记录了它的长度)
这里向主机申请的时候,需要填写自己的server_id,来通知master连上来的是谁。
如果现在有两个slave连上来并都申明自己的server_id为2,MySQL的master就有点无所适从了。
初步怀疑是slave的IO线程连上以后,master过了一段时间(ms级别的)才发现,然后把新的连接断掉,所以slave io线程才会报警:
100817 19:45:45 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘mysql-bin.000033’ at postion 271148235
100817 19:45:45 [Note] Slave: received end packet from server, apparent master shutdown:
说收到主机发起的end packet(主机每次发送一个event过来,如果1、收到的包数据有误或者2、不能由接收到的包解出正确的event来,slave io判定复制有问题,
而其中end packet属于第一种情况
对应的代码为sql/slave.cc的read_event函数:
/* Check if eof packet */
if (len < 8 && mysql->net.read_pos[0] == 254)
{
sql_print_information(“Slave: received end packet from server, apparent ”
“master shutdown: %s”,
mysql_error(mysql));
DBUG_RETURN(packet_error);
}

由于MySQL的io有自动重连的机制,所以MySQL的io线程又连主机,并且还连上了。
master过了一段时间(ms级别的)又发现已经有了server_id=2的slave连着的,把它重新断掉了。
看了一下master的代码sql/sql_parse.cc的dispatch_command函数:
mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
unregister_slave(thd,1,1);
发送binlog以后,它会做一个unregister_slave,它认为是同一个slave change master连接过来,“理所当然的”它就把前面的连接给干掉了。
周而复始,就产生了这样的错误。
解决的办法很简单,就是不要用同样的server_id的slave同时连一台master。server_id可以设置的很大,所以不要顾虑,赶紧重设吧。

不知道有没有人想过为什么server_id不能设置为0
在my.cnf里面是没有办法设置server_id=0的,不信的话,你试试,正常情况下,它不会让你start slave的。代码如下sql/slave.cc的start_slave_thread函数:
if (!server_id)
{
if (start_cond)
pthread_cond_broadcast(start_cond);
if (start_lock)
pthread_mutex_unlock(start_lock);
sql_print_error(“Server id not set, will not start slave”);
DBUG_RETURN(ER_BAD_SLAVE);
}
不过,我还真的没有测试过这种情况,呵呵。
当然,server_id设置为0的情况也有,但是不是你或者我,而是mysqlbinlog,它的server_id可以设置为0.
原因如下:如果mysqlbinlog的server_id为0的话,它就会把正常的slave给停掉了。万一它的server_id为5,它连上去以后就会把真正的server-id为5的slave断掉了。
server_id设置为0我印象中还有一个不同点,是关于MySQL master发送binlog是否会停止的,但是就是想不起来了,老了。代码也没有找到确凿的证据;先这样把

may your success!