由上可知,在MySQL 5.1及以上的RC隔离级别下,语句级Binlog在DR上执行的结果是不正确的!
那么,MySQL 5.0呢?5.0允许RC下语句级Binlog,是不是说很容易产生DB/DR不一致呢?
事实上,在5.0重复上述一个测试,并不存在这个问题,原因是5.0的RC与5.1的RR使用类似的并发和上锁机制,也就是说,MySQL 5.0的RC与5.1及以上的RC可能存在兼容性问题。
下面看看RR是怎么解决这个问题的。
2. 默认隔离级别-可重复读导致RC隔离级别DB/DR不一致的原因是:RC不可重复读,而Binlog要求SQL串行化!
在RR下,重复以上测试
会话1
会话2
use test;
#初始化数据
create table t1(c1 int, c2 int) engine=innodb;
create table t2(c1 int, c2 int) engine=innodb;
insert into t1 values(1,1), (2,2);
insert into t2 values(1,1), (2,2);
#设置隔离级别
set tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)
#连续更新两次
mysql> Begin;
Query OK, 0 rows affected (0.03 sec)
mysql> update t2 set c2 = 3 where c1 in (select c1 from t1);
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> update t2 set c2 = 4 where c1 in (select c1 from t1);
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from t2;
+------+------+
| c1 | c2 |
+------+------+
| 1 | 4 |
| 2 | 4 |
+------+------+
2 rows in set (0.00 sec)
mysql> commit;
#设置隔离级别
set tx_isolation=' repeatable-read';
Query OK, 0 rows affected (0.00 sec)
#两次更新之间执行删除
mysql> delete from t1 where c1 = 2;
--阻塞,直到会话1提交
Query OK, 1 row affected (18.94 sec)
与RC隔离级别不同的是,在RR中,由于保证可重复读,会话2的delete语句会被会话1阻塞,直到会话1提交。
在RR中,会话1语句update t2 set c2 = 3 where c1 in (select c1 from t1)会先在t1的记录上S锁(5.1的RC中不会上这个锁,但5.0的RC会),接着在t2的满足条件的记录上X锁。由于会话1没提交,会话2的delete语句需要等待会话1的S锁释放,于是阻塞。