MySQL幻讀解決測試

MySQL在可重复读的隔离级别解决了幻读的现象,接下来实际来测试一下看看。

幻读的概念

幻读(Phantom read)发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

临键锁的概念

临键锁是行级锁的一种,它锁定索引项本身和索引范围。其他事务不能在锁范围内插入数据,因此可解决幻读问题。

测试准备

创建user表,并插入几条数据(id为1,2,3,4,5,7)作为测试。

<code>CREATE TABLE user
(
   id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
   name varchar(30),
   age int(11),
   email varchar(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO user (id, name, age, email) values (1, "test1", 21, "[email protected]");
INSERT INTO user (id, name, age, email) values (2, "test2", 22, "[email protected]");
INSERT INTO user (id, name, age, email) values (3, "test3", 23, "[email protected]");
INSERT INTO user (id, name, age, email) values (4, "test4", 24, "[email protected]");
INSERT INTO user (id, name, age, email) values (5, "test5", 25, "[email protected]");
INSERT INTO user (id, name, age, email) values (7, "test7", 27, "[email protected]");/<code>

确认事务隔离级别和session是否自动提交

show variables like 'transaction_isolation'; 查看事务级别

show session variables like 'autocommit'; 查看session自动提交是否开启

set autocmmit = 0 来关闭自动提交

MySQL幻读解决测试

开始测试

启动两个session, 确保事务隔离级别以及session的自动提交是关闭的。

sessionA, begin开启事务,然后select查询id > 1并且id < 8的数据。


MySQL幻读解决测试

SessionA 临键锁锁定id 大于1小于8的范围

sessionB, begin开启事务,然后插入一条id为6的数据。


MySQL幻读解决测试

SessionB 插入Id等于6的记录

SessionA, 这个时候再次查询id大于1小于8,可以看到结果没有发生变化,SessionA没有看到记录6的存在。


MySQL幻读解决测试

SessionA,发现没有记录6的数据,尝试插入ID为6的记录,发现会等待锁超时报错。因为SessionB没有提交。

MySQL幻读解决测试

SessionB commit把事务提交。

MySQL幻读解决测试

SessionA再次查询id大于1小于8的记录,仍然没有记录6的存在,然后记录添加记录6,这个会报主键已存在的错误。

MySQL幻读解决测试

测试总结

上述测试证明了MySQL可重复读的事务隔离级别解决了幻读的现象。并且当另外事务尝试去做插入的时候,通过临键锁来防止数据错误。


分享到:


相關文章: