MySQL InnoDB非阻塞式读的实现原理
以前在学习《数据库概论》这门课程的时候,了解到在可重复读这个隔离级别下,一个事务内同一个SELECT查询的多次执行会返回相同的结果,而这个是对查询返回的记录加共享锁来实现的。这样,别的事务如果要更新相同的记录的话就必要要等前一个事务先释放锁。说白了,这就是通过数据库三级*协议(三级*协议:在一级*协议的基础上,事务T在读取数据R之前,必须先对其加上S锁,直到事务结束后才释放。三级*协议可以防止丢失更新、脏读和不可重复读)实现的。
但是最近在Mysql数据库上测试的时候,发现一个事务在可重复读隔离级别下查询了某个记录,在没有提交前,别的事务居然可以更新、删除这个记录并且顺利地提交,而且在原事务内再次查询的时候,记录还和第一次返回一样。开始觉得太不可思议了,这和自己的理解完全不一样,上网查阅了相关的资料后才明白,原来Mysql使用了Multi-Version Concurrent Controll多版本并发控制的技术来实现非阻塞式读的。
MySQL InnoDB使用MVCC来实现非阻塞式读,在这个模式下,数据库会为每个数据记录维护多个版本。在可重复读隔离级别下,事务第一次查询记录的时候,会记录下一个时间点,在该事务内如果再次(可是以不同的SELECT)查询相同的数据的话,事务只会取时间点前的记录版本,这样在不需要对数据加锁的情况下就实现了可重复读的隔离级别了,而且并发性能更好。在同一事务内多次查询同一数据,也不是就返回一个固定的记录版本,如果事务先查询了某个记录,随后自己又更新了这个数据,等再查询该数据的话,返回的就是自己更新过后的数据版本了。
对于读已提交这个隔离级别,事务内的查询操作总是会取数据最新的有效版本,即最新的、别的事务已经提交的内容。通过MVCC,事务内的查询操作(这里排除SELECT FOR UPDATE和SELECT LOCK IN SHARE MODE两种情况)就不需要对数据加任何锁了,这样,别的事务就可以在不影响原事务的前提下*的操作这些记录,极大的提升了并发性能。
推荐阅读
-
MySQL InnoDB非阻塞式读的实现原理
-
MySQL~InnoDB引擎解决脏读,不可重复读,幻读,丢失更新的原理(lock事务锁、自增长锁、Record Lock、Gap Lock、Next-Key Lock、死锁)
-
Python实现的服务器示例小结【单进程、多进程、多线程、非阻塞式】
-
java原子化结点结合非阻塞思想以实现链表式队列的插入(可做无阻塞队列使用)
-
java原子化结点结合非阻塞思想以实现链表式队列的插入(可做无阻塞队列使用)
-
c# 使用Task实现非阻塞式的I/O操作
-
MySQL~InnoDB引擎解决脏读,不可重复读,幻读,丢失更新的原理(lock事务锁、自增长锁、Record Lock、Gap Lock、Next-Key Lock、死锁)