上周看到datacharmer放出来了一个检测主从复制是否正常的shell脚本,
就转载了:《检测mysql主从复制是否正常的shell脚本》。
脚本虽好用,但是感觉功能比较一般,只能检测到问题,无法在根本上解决问题。
http://mysqlmusings.blogspot.com/2011/04/replication-event-checksum.html
mysql 主从复制(replication) 同步速度快,简单易用,并且相当可靠。
不过,当你检查到主从数据不一致的时候,很难判断出问题所在(软件问题?硬件问题?网络传输问题?)
一个比较常见的情况是软硬件或者网络传输出错,导致主服务器上运行的sql语句与从服务器上运行的sql语句不一致(称为event corrupt)。
为了解决这个问题, mysql的开发人员在 5.6 Milestone Development Release版本中加入了 replication event checksum(主从复制事件校验)功能。
当一个event被写入binary log(二进制日志)的时候,checksum也同时写入binary log,然后在event通过网络传输到从服务器(slave)之后,再在从服务器中对其进行验证并写入从服务器的relay log.
由于每一步都记录了event和checksum,所以我们可以很快地找出问题所在。
checksum使用zlib中的CRC-32算法,更具体地讲,是ISO-3309 CRC-32算法,虽然此算法效率非常高,但总是带来了一些额外的计算,至于会影响性能到怎样的地步,目前还没有benchmark。
[图1]
如图1所示,当箭头离开thread的时候,就可以生成checksum;当箭头进入thread的时候,就可以对checksum进行校验了。
不过由于某些原因,并非在所有的箭头处都进行了checksum。
event checksum功能,引入了三个新的参数:
binlog_checksum
默认为NONE, 表示在图1的箭头1 不生成checksum, 这样就可以兼容旧版本的mysql。
此外,就只能设置为CRC32了。
master_verify_checksum
可以设置为0或者1(默认为0)。 对应于图1中的箭头2。
设置为1的话,不仅dump thread会对event进行校验,当master上执行show binlog events的时候,也会对event进行校验。
设置为1,可以保证event被完整无缺地写入到主服务器的binlog中了。
不过,通常这个都设置为0。
slave_sql_verify_checksum
与master_verify_checksum类似,这个也只能设置为0或者1(默认为1)。
设置为1, 在图1的箭头4处会生成checksum,然后在箭头5处会对checksum进行验证。
看完这三个参数,再与图1进行一下比较,会发现在箭头3那里没有进行任何验证。
原文中的解释是:
在箭头4的时候,当IO thread把event写入到relay log的时候,会验证checksum。
This is not necessary since the checksum is verified when the event is written to the relay log at point 4, and the I/O thread just does a straight copy of the event。
当checksum出错的时候,会是怎样的呢?试试看吧。
master> CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY, name CHAR(50));
Query OK, 0 ROWS affected (0.04 sec)
master> INSERT INTO t1(name) VALUES ('Mats'),('Luis');
Query OK, 2 ROWS affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
master> SHOW BINLOG EVENTS FROM 261;
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| master-bin.000001 | 261 | Query | 1 | 333 | BEGIN |
| master-bin.000001 | 333 | Intvar | 1 | 365 | INSERT_ID=1 |
| master-bin.000001 | 365 | Query | 1 | 477 | USE `test`; INSERT INTO t1(name) VALUES ('Mats'),('Luis') |
| master-bin.000001 | 477 | Query | 1 | 550 | COMMIT |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
4 ROWS IN SET (0.00 sec)
这里与老版本的mysql一致, 暂时还看不到checksum的影子。
接下来直接修改binlog文件,把Mats改成Matz。
#master_verify_checksum默认为0.
master> SHOW BINLOG EVENTS FROM 261;
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| master-bin.000001 | 261 | Query | 1 | 333 | BEGIN |
| master-bin.000001 | 333 | Intvar | 1 | 365 | INSERT_ID=1 |
| master-bin.000001 | 365 | Query | 1 | 477 | USE `test`; INSERT INTO t1(name) VALUES ('Matz'),('Luis') |
| master-bin.000001 | 477 | Query | 1 | 550 | COMMIT |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
4 ROWS IN SET (0.00 sec)
master> SET GLOBAL MASTER_VERIFY_CHECKSUM=1;
Query OK, 0 ROWS affected (0.00 sec)
master> SHOW BINLOG EVENTS FROM 261;
ERROR 1220 (HY000): Error WHEN executing command SHOW BINLOG EVENTS: Wrong offset OR I/O error
果真就校验出错了。
按照以下的步骤,可以在从服务器上进行类似的实验:
1 START SLAVE IO_THREAD.
2 一段时间之后 STOP SLAVE.
3 直接编辑relay log
4 START SLAVE。
slave> SHOW SLAVE STATUS\G
*************************** 1. ROW ***************************
.
.
.
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 550
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 419
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
.
.
.
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1594
Last_SQL_Error: Relay log READ failure: Could NOT parse
relay log event entry. The possible
reasons are: the master's binary log is
corrupted...
.
.
.
Last_SQL_Error_Timestamp: 110406 09:41:40
1 row in set (0.00 sec)
看来是相当管用啊。
不过,这也只能发现错误,却不知道是哪条SQL语句出了问题。
mysql team又推出了新版本的mysqlbinlog。
原来的mysqlbinlog主要作用就是把mysql二进制日志转化为文本形式,现在又加上了校验功能。
$ client/mysqlbinlog --verify-binlog-checksum master-bin.000001
.
.
.
# at 261
#110406 8:35:28 server id 1 end_log_pos 333 CRC32 0xed927ef2 Query thread_id=1...
SET TIMESTAMP=1302071728/*!*/;
BEGIN
/*!*/;
# at 333
#110406 8:35:28 server id 1 end_log_pos 365 CRC32 0x01ed254d Intvar
SET INSERT_ID=1/*!*/;
ERROR: Error IN Log_event::read_log_event(): 'Event crc check failed! Most likely...
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
顺便提一句,CRC32也打印出来了(32位的)。
参考:
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_binlog-checksum
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_master-verify-checksum
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_slave-sql-verify-checksum
mysql 5.6 下载地址:
http://dev.mysql.com/
就转载了:《检测mysql主从复制是否正常的shell脚本》。
脚本虽好用,但是感觉功能比较一般,只能检测到问题,无法在根本上解决问题。
http://mysqlmusings.blogspot.com/2011/04/replication-event-checksum.html
mysql 主从复制(replication) 同步速度快,简单易用,并且相当可靠。
不过,当你检查到主从数据不一致的时候,很难判断出问题所在(软件问题?硬件问题?网络传输问题?)
一个比较常见的情况是软硬件或者网络传输出错,导致主服务器上运行的sql语句与从服务器上运行的sql语句不一致(称为event corrupt)。
为了解决这个问题, mysql的开发人员在 5.6 Milestone Development Release版本中加入了 replication event checksum(主从复制事件校验)功能。
当一个event被写入binary log(二进制日志)的时候,checksum也同时写入binary log,然后在event通过网络传输到从服务器(slave)之后,再在从服务器中对其进行验证并写入从服务器的relay log.
由于每一步都记录了event和checksum,所以我们可以很快地找出问题所在。
checksum使用zlib中的CRC-32算法,更具体地讲,是ISO-3309 CRC-32算法,虽然此算法效率非常高,但总是带来了一些额外的计算,至于会影响性能到怎样的地步,目前还没有benchmark。
[图1]
如图1所示,当箭头离开thread的时候,就可以生成checksum;当箭头进入thread的时候,就可以对checksum进行校验了。
不过由于某些原因,并非在所有的箭头处都进行了checksum。
event checksum功能,引入了三个新的参数:
binlog_checksum
默认为NONE, 表示在图1的箭头1 不生成checksum, 这样就可以兼容旧版本的mysql。
此外,就只能设置为CRC32了。
master_verify_checksum
可以设置为0或者1(默认为0)。 对应于图1中的箭头2。
设置为1的话,不仅dump thread会对event进行校验,当master上执行show binlog events的时候,也会对event进行校验。
设置为1,可以保证event被完整无缺地写入到主服务器的binlog中了。
不过,通常这个都设置为0。
slave_sql_verify_checksum
与master_verify_checksum类似,这个也只能设置为0或者1(默认为1)。
设置为1, 在图1的箭头4处会生成checksum,然后在箭头5处会对checksum进行验证。
看完这三个参数,再与图1进行一下比较,会发现在箭头3那里没有进行任何验证。
原文中的解释是:
在箭头4的时候,当IO thread把event写入到relay log的时候,会验证checksum。
This is not necessary since the checksum is verified when the event is written to the relay log at point 4, and the I/O thread just does a straight copy of the event。
当checksum出错的时候,会是怎样的呢?试试看吧。
master> CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY, name CHAR(50));
Query OK, 0 ROWS affected (0.04 sec)
master> INSERT INTO t1(name) VALUES ('Mats'),('Luis');
Query OK, 2 ROWS affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
master> SHOW BINLOG EVENTS FROM 261;
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| master-bin.000001 | 261 | Query | 1 | 333 | BEGIN |
| master-bin.000001 | 333 | Intvar | 1 | 365 | INSERT_ID=1 |
| master-bin.000001 | 365 | Query | 1 | 477 | USE `test`; INSERT INTO t1(name) VALUES ('Mats'),('Luis') |
| master-bin.000001 | 477 | Query | 1 | 550 | COMMIT |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
4 ROWS IN SET (0.00 sec)
这里与老版本的mysql一致, 暂时还看不到checksum的影子。
接下来直接修改binlog文件,把Mats改成Matz。
#master_verify_checksum默认为0.
master> SHOW BINLOG EVENTS FROM 261;
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
| master-bin.000001 | 261 | Query | 1 | 333 | BEGIN |
| master-bin.000001 | 333 | Intvar | 1 | 365 | INSERT_ID=1 |
| master-bin.000001 | 365 | Query | 1 | 477 | USE `test`; INSERT INTO t1(name) VALUES ('Matz'),('Luis') |
| master-bin.000001 | 477 | Query | 1 | 550 | COMMIT |
+-------------------+-----+------------+-----------+-------------+-----------------------------------------------------------+
4 ROWS IN SET (0.00 sec)
master> SET GLOBAL MASTER_VERIFY_CHECKSUM=1;
Query OK, 0 ROWS affected (0.00 sec)
master> SHOW BINLOG EVENTS FROM 261;
ERROR 1220 (HY000): Error WHEN executing command SHOW BINLOG EVENTS: Wrong offset OR I/O error
果真就校验出错了。
按照以下的步骤,可以在从服务器上进行类似的实验:
1 START SLAVE IO_THREAD.
2 一段时间之后 STOP SLAVE.
3 直接编辑relay log
4 START SLAVE。
slave> SHOW SLAVE STATUS\G
*************************** 1. ROW ***************************
.
.
.
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 550
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 419
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
.
.
.
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1594
Last_SQL_Error: Relay log READ failure: Could NOT parse
relay log event entry. The possible
reasons are: the master's binary log is
corrupted...
.
.
.
Last_SQL_Error_Timestamp: 110406 09:41:40
1 row in set (0.00 sec)
看来是相当管用啊。
不过,这也只能发现错误,却不知道是哪条SQL语句出了问题。
mysql team又推出了新版本的mysqlbinlog。
原来的mysqlbinlog主要作用就是把mysql二进制日志转化为文本形式,现在又加上了校验功能。
$ client/mysqlbinlog --verify-binlog-checksum master-bin.000001
.
.
.
# at 261
#110406 8:35:28 server id 1 end_log_pos 333 CRC32 0xed927ef2 Query thread_id=1...
SET TIMESTAMP=1302071728/*!*/;
BEGIN
/*!*/;
# at 333
#110406 8:35:28 server id 1 end_log_pos 365 CRC32 0x01ed254d Intvar
SET INSERT_ID=1/*!*/;
ERROR: Error IN Log_event::read_log_event(): 'Event crc check failed! Most likely...
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
顺便提一句,CRC32也打印出来了(32位的)。
参考:
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_binlog-checksum
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_master-verify-checksum
http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_slave-sql-verify-checksum
mysql 5.6 下载地址:
http://dev.mysql.com/
from :http://www.zhaokunyao.com/archives/2387