InnoDB 讀大量數據時會加讀鎖么?


結論

默認不會加讀鎖!但 MySQL InnoDB 的可重復讀並不保證避免幻讀,需要應用使用加鎖讀來保證。而這個加鎖度使用到的機制就是 next-key locks。

隔離級別說明

MySQL InnoDB事務的隔離級別有四級,默認是“可重復讀”(REPEATABLE READ)。

  • 未提交讀(READ UNCOMMITTED)。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據(臟讀)。
  • 提交讀(READ COMMITTED)。本事務讀取到的是最新的數據(其他事務提交后的)。問題是,在同一個事務里,前后兩次相同的SELECT會讀到不同的結果(不重復讀)。
  • 可重復讀(REPEATABLE READ)。在同一個事務里,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(稍后解釋)。
  • 串行化(SERIALIZABLE)。讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。

四個級別逐漸增強,每個級別解決一個問題。

  • 臟讀,最容易理解。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據。
  • 不重復讀。解決了臟讀后,會遇到,同一個事務執行過程中,另外一個事務提交了新數據,因此本事務先后兩次讀到的數據結果會不一致。
  • 幻讀。解決了不重復讀,保證了同一個事務里,查詢的結果都是事務開始並且第一次查詢時的狀態(一致性)。但是,如果另一個事務同時提交了新數據,雖然本事務再次按照相同的條件查找會得到相同的結果集,但是本事務指定更新時,就會“驚奇的”發現了這些新數據,貌似之前讀到的數據是“鬼影”一樣的幻覺。

所以 InnoDB 默認還是會出現幻讀現象的,所以還是可能會加鎖。

幻讀的演示

摘自 CSDN博主「南C哥」-MySQL中幻讀現象

銀行A開啟了一個事務窗口,查詢當前系統中有沒有"wangwu"用戶,發現沒有,銀行B也開啟了一個事務窗口,查詢當前系統中也沒有"wangwu"用戶,銀行A先創建"wangwu"用戶並且提交,由於可重復讀取,銀行B在一次事務中必須保證查詢的數據一致性,因此查詢不到"wangwu",結果銀行B窗口認為wangwu沒有被注冊想注冊"wangwu"用戶,就創建"wangwu"用戶結果發現系統提示"wangwu"用戶已經被注冊",但是在本次事務中又查詢不到"wangwu",就好像出現幻覺一樣

create table user(
  id int primary key,
  username varchar(30),
  money double
);
insert into user values(1,'zhangsan',100);
insert into user values(2,'lisi',100);

打開兩個MySQL窗口

image

解決幻讀可以提高事務隔離級別為 Serializable (串行化),它是使用的共享鎖,當然 MySQL 有鎖的類型:共享鎖(S)、排他鎖(X)、意向共享(IS)、意向排他(IX)。 還有非鎖定讀:不需要等待訪問行上的鎖釋放,讀取行的一個快照。

具體參照 Innodb鎖機制:Next-Key Lock 淺談


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM