mysql三大日志
熟悉mysql的小伙伴都知道mysql的三大日志,undo,redo,binlog 其中 undo和redo用于事务的回滚和保持数据的持久化,两者是属于 innodb引擎层,而binlog则属于数据mysql服务层主要用于mysql主从复制模式中的数据同步。
主从数据不一致
在mysql早期的版本中,搭建mysql主从模式集群,mysql事务隔离级别RC下产生主从数据不一致的问题,这也是为什么mysql默认的事务隔离级别是RR而不是RC,这是因为当时RC级别下binlog记录的格式为’Statement‘,这种格式下会根据事务提交的顺序将执行的sql完整的记录下来,记下来我们举例说明。
准备表和数据
create table test.t3 ( a int(20) null, b int(20) null );
案例一
开启两个事务
事务1 | 事务2 |
set autocommit=0; update t3 set b=8 where a=2; commit; | set autocommit=0; update t3 set b=2 where a=4; commit |
在事务1中我们将字段b为2的值全部更新为8,但是在事务准备提交的时候,事务2中的sql执行并快于事务1进行提交
这时候表中最终的数据为:
这个结果是么偶有任何问题的。
但是当从节点通过binlog同步主节点上的数据时其结果为:
很明显这时候主节点和从节点的数据变得不一致
原因
这是因为在RC隔离级别下binlog的格式为statement,上面案例中执行的sql会被binlog以事务提交的顺序记录
1 update t3 set b=2 where a=4;
2 update t3 set b=8 where a=2;
从节点按照这个顺序执行的到的结果肯定是和主节点不一致
解决方法
mysql之后的版本中在 Rc和RR级别下,binlog的默认的记录格式改为row,row格式是基于sql逻辑变化而记录,还是以上面的案例为参考,我们取看下当格式为row下binlog日志是怎么记录的;
@1 表示 表中 字段 a @2表示字段b
通过这种记录方式,从节点按照书屋提交顺序来执行sql更新逻辑就不会出现和主节点数据不一致
说明:
本次用的mysql8ben来想着通过 set session binlog_format 将blog格式改为statement ,但是执行sql的时候报错,说是RR,Rc下只能默认为row