所谓半同步,是指从库完全接收到主库传来的binlog数据,并将数据写入到realy log后,主库才能提交事务, 那么理论上,在主库执行大事务并正常提交事务后出现宕机,这时从库虽然接收到了全部的binlog, 但是realy log可能还没有解析重放完成, 导致从库查询的数据是滞后的,等realy log解析重放完成后,数据才会一致, 也就是半同步复制在某些场景下,数据不是强一致性的,而是弱一致性或最终一致性。
下面通过实验来验证这个猜想:
主库:192.168.1.100 MySQL 5.7.22 Redhat7.5 从库:192.168.1.200 MySQL 5.7.22 Redhat7.5
启用半同步复制
主库
准备测试数据
mysql> use cjc Database changed mysql> select count(*) from t1; +----------+ | count(*) | +----------+ | 11534336 | +----------+ 1 row in set (5.88 sec) mysql> create table t2 like t1; Query OK, 0 rows affected (0.33 sec)
从库
检查半同步状态
mysql> show global status like '%semi%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.62 sec)
主从同步状态
mysql> show slave status\G;
主库、从库执行脚本,查看t2表数据量和时间
准备脚本
[mysql@cjc-db-01 ~]$ head -n 2 1.sh mysql -uroot -p1 -e "select now(),count(*) from cjc.t2;" mysql -uroot -p1 -e "select now(),count(*) from cjc.t2;" [mysql@cjc-db-01 ~]$ cat 1.sh |wc -l 12312
执行脚本
[mysql@dcs02 ~]$ sh 1.sh > 1.log [mysql@dcs02 ~]$ tail -10f 1.log
主库:模拟大事务
mysql> insert into t2 select * from t1; Query OK, 11534336 rows affected (6 min 57.18 sec) Records: 11534336 Duplicates: 0 Warnings: 0
主库:在10:39:40事务结束,查询t2表数据量为11534336
2022-12-29 10:34:360 now()count(*) 2022-12-29 10:35:100 now()count(*) 2022-12-29 10:35:590 now()count(*) 2022-12-29 10:36:580 now()count(*) 2022-12-29 10:38:110 now()count(*) 2022-12-29 10:39:4011534336 now()count(*) 2022-12-29 10:39:4711534336 now()count(*) 2022-12-29 10:39:5411534336 now()count(*)
强制关闭主库,模拟意外宕机
[root@cjc-db-01 ~]# ps -ef|grep mysql mysql 2318 1 5 09:10 pts/0 00:04:25 mysqld --defaults-file=/etc/my.cnf --user=mysql [root@cjc-db-01 ~]# kill -9 2318
从库:
在10:45:51查询t2表数据量为11534336,比主库慢了6分11秒,
也就是主库10:40:00宕机后,从库切换为主库,在10:40:00到10:45:50期间,t2表数据量和真实数据量不一致,
数据量为0,实际是11534336,5分钟后,relay log完全解析入库后,数据一致。
[mysql@dcs02 ~]$ sh 1.sh > 1.log [mysql@dcs02 ~]$ tail -10f 1.log now()count(*) 2022-12-29 10:43:000 now()count(*) 2022-12-29 10:43:510 now()count(*) 2022-12-29 10:44:520 now()count(*) 2022-12-29 10:45:5111534336 now()count(*) 2022-12-29 10:45:5811534336 now()count(*) 2022-12-29 10:46:0611534336 now()count(*) 2022-12-29 10:46:1211534336