其实,RR隔离级别的防止幻象主要是针对写操作的,即只保证写操作的可串行化,因为只有写操作影响Binlog;而读操作是通过MVCC来保证一致性读(无幻象)。
然而,可串行化隔离级别要求读写可串行化。使用可串行化重做以上测试。
会话1
会话2
use test;
#初始化数据
create table t3(c1 int primary key, c2 int) engine=innodb;
#设置隔离级别
set tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
mysql> Begin;
Query OK, 0 rows affected (0.03 sec)
mysql> select * from t3 where c1 = 1;
Empty set (0.00 sec)
mysql> select * from t3 where c1 = 1;
Empty set (0.00 sec)
mysql> update t3 set c2 =2 where c1 = 1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql> select * from t3 where c1 = 1;
Empty set (0.00 sec)
mysql> commit;
#设置隔离级别
set tx_isolation='SERIALIZABLE';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t3 values(1,1);
#阻塞,直到会话1提交
Query OK, 1 row affected (48.90 sec)
设置为串行化后,会话2的插入操作被阻塞。由于在串行化下,查询操作不在使用MVCC来保证一致读,而是使用S锁来阻塞其他写操作。因此做到读写可串行化,然而换来就是并发性能的大大降低。
4. 小结MySQL使用可重复读来作为默认隔离级别的主要原因是语句级的Binlog。RR能提供SQL语句的写可串行化,保证了绝大部分情况(不安全语句除外)的DB/DR一致。
另外,通过这个测试发现MySQL 5.0与5.1在RC下表现是不一样的,可能存在兼容性问题。