結論
默認不會加讀鎖!但 MySQL InnoDB 的可重復讀並不保證避免幻讀,需要應用使用加鎖讀來保證。而這個加鎖度使用到的機制就是 next-key locks。
隔離級別說明
MySQL InnoDB事務的隔離級別有四級,默認是“可重復讀”(REPEATABLE READ)。
- 未提交讀(READ UNCOMMITTED)。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據(臟讀)。
 - 提交讀(READ COMMITTED)。本事務讀取到的是最新的數據(其他事務提交后的)。問題是,在同一個事務里,前后兩次相同的SELECT會讀到不同的結果(不重復讀)。
 - 可重復讀(REPEATABLE READ)。在同一個事務里,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(稍后解釋)。
 - 串行化(SERIALIZABLE)。讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。
 
四個級別逐漸增強,每個級別解決一個問題。
- 臟讀,最容易理解。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據。
 - 不重復讀。解決了臟讀后,會遇到,同一個事務執行過程中,另外一個事務提交了新數據,因此本事務先后兩次讀到的數據結果會不一致。
 - 幻讀。解決了不重復讀,保證了同一個事務里,查詢的結果都是事務開始並且第一次查詢時的狀態(一致性)。但是,如果另一個事務同時提交了新數據,雖然本事務再次按照相同的條件查找會得到相同的結果集,但是本事務指定更新時,就會“驚奇的”發現了這些新數據,貌似之前讀到的數據是“鬼影”一樣的幻覺。
 
所以 InnoDB 默認還是會出現幻讀現象的,所以還是可能會加鎖。
幻讀的演示
銀行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窗口

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