mysql 面试知识点笔记(七)RR如何避免幻读及非阻塞读、范式
2019獨角獸企業重金招聘Python工程師標準>>>
表象:快照讀(非阻塞讀)--偽MVCC (Multi-Version Concurrent Controll多版本并發控制)
內在:next-key鎖(record鎖+gap鎖) rr serializabel 都支持gap鎖
問:在rr下對主鍵索引或者唯一索引會用gap鎖嘛?
如果where條件全部命中,則不會用gap鎖,只會加record鎖(行鎖)
如果部分命中或全不命中則會加gap鎖
比如查詢id in(1,3,5) ,id是主鍵。?查到了 1、3 ,沒有查到5則會加gap鎖,在3~+∞的區間。
如果加鎖是主鍵之外的索引 則會在當前索引以及主鍵索引上都上排他鎖。如下圖:
-- 創建測試表 CREATE TABLE `tb`( `name` varchar(10) NOT NULL, `id` int(100) NOT NULL DEFAULT '0', PRIMARY KEY(`name`), UNIQUE KEY `unique_id` (`id`) ) ENGINE = INNODB DEFAULT CHARSET=utf8;插入以下數據:
不加gap鎖的情況
-- 第一個會話 SELECT @@tx_isolation; set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;start TRANSACTION; DELETE from tb where id = 9; -- 執行完delete之后執行事務2的insert 是成功的 因為id=9存在 只加了行鎖 ROLLBACK;-- 第二個會話 SELECT @@tx_isolation; set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;start TRANSACTION; insert into tb VALUES('i',10); ROLLBACK;加gap鎖的情況
-- 1、全不命中 -- 第一個會話 start TRANSACTION; DELETE from tb where id = 7; -- 這里在執行事務2的insert 則會block 證明加了gap鎖 ROLLBACK;-- 第二個會話 start TRANSACTION; insert into tb VALUES('i',8); ROLLBACK;-- 2、部分命中情況 -- 第一個會話 start TRANSACTION; -- 這里命中5和9 7沒有命中 在6~8加了gap鎖 如果是in (5,6,9) 則不會加gap鎖 select * from tb where id in (5,7,9) lock in share mode; ROLLBACK;-- 第二個會話 start TRANSACTION; -- 沒有block insert into tb VALUES('i1',4); -- 有block insert into tb VALUES('i2',7); -- 有block insert into tb VALUES('i3',8); -- 沒有block insert into tb VALUES('i4',10); ROLLBACK;- 非唯一索引都是到點的左開右閉區間
測試表 非唯一索引
CREATE TABLE `tb1`( `name` varchar(10) NOT NULL, `id` int(100) NOT NULL DEFAULT '0', PRIMARY KEY(`name`), KEY `non_unique_id` (`id`) ) ENGINE = INNODB DEFAULT CHARSET=utf8; -- 第一個會話 start TRANSACTION; DELETE from tb1 where id = 9; -- 此時執行會話2的insert 會被block ROLLBACK;-- 第二個會話 start TRANSACTION; insert into tb1 VALUES('test',9); #6-11的左開右閉區間 -- 不會block insert into tb1 VALUES('test1',5); -- 會block insert into tb1 VALUES('test2',7); -- 不會block insert into tb1 VALUES('test3',12); -- bb是主鍵c的左邊 所以不會block insert into tb1 VALUES('bb',6); -- dd是主鍵c的右邊 所以會block insert into tb1 VALUES('dd',6); -- e是主鍵f的左邊 所以不會block insert into tb1 VALUES('e',11); -- g是主鍵f的右邊 所以會block insert into tb1 VALUES('g',11); ROLLBACK;- 不走索引(會對所有的gap加鎖 就是鎖表了)
測試表 無索引
CREATE TABLE `tb2`( `name` varchar(10) NOT NULL, `id` int(100) NOT NULL DEFAULT '0', PRIMARY KEY(`name`) ) ENGINE = INNODB DEFAULT CHARSET=utf8; -- 第一個會話 start TRANSACTION; DELETE from tb2 where id = 9; ROLLBACK;-- 第二個會話 start TRANSACTION; -- 鎖表 這里的insert是block的 insert into tb2 VALUES('test',2); ROLLBACK;MySQL InnoDB非阻塞式讀的實現原理:MVCC
MySQL InnoDB使用MVCC來實現非阻塞式讀,在這個模式下,數據庫會為每個數據記錄維護多個版本。在可重復讀隔離級別下,事務第一次查詢記錄的時候,會記錄下一個時間點,在該事務內如果再次(可是以不同的SELECT)查詢相同的數據的話,事務只會取時間點前的記錄版本,這樣在不需要對數據加鎖的情況下就實現了可重復讀的隔離級別了,而且并發性能更好。在同一事務內多次查詢同一數據,也不是就返回一個固定的記錄版本,如果事務先查詢了某個記錄,隨后自己又更新了這個數據,等再查詢該數據的話,返回的就是自己更新過后的數據版本了。此處來自:https://ouyanggod.iteye.com/blog/2165668
范式參考:https://www.cnblogs.com/gdwkong/p/9012262.html
轉載于:https://my.oschina.net/pentakill/blog/3045452
總結
以上是生活随笔為你收集整理的mysql 面试知识点笔记(七)RR如何避免幻读及非阻塞读、范式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows下压缩包安装Mysql
- 下一篇: java ReentrantLock 锁