事務併發的三種問題:
髒讀:讀取了別的事務未提交的數據。
不可重複讀:你讀取過的數據 , 再次讀取出來被人改了。
幻讀:同一個事務,第1次和第2次讀出來的記錄數不一樣。
隔離級別 | 讀未提交 | 讀已提交 | 可重複讀 | 可串行化 |
| ReadUncommitted | ReadCommitted | REPEATABLE READ | SERIALIZABL |
理論鎖 | 寫事務阻塞寫,但不阻塞讀。 | 寫事務會阻塞寫、讀事務,但是讀不阻塞寫, | 寫阻塞讀寫,讀阻塞寫(鎖所有行) | 讀加共享鎖,寫加排他鎖(鎖表) |
Mysql實際鎖 | 只有寫阻塞寫 | 只有寫阻塞寫 | 只有寫阻塞寫 | 寫阻塞讀、寫, 讀阻塞寫。 |
可能存在問題 | 髒讀、不可重複讀、幻讀 | 不可重複讀、幻讀 | 幻讀 | 無 |
Mysql實際存在問題 | 髒讀、不可重複讀、幻讀 | 不可重複讀、幻讀 | 無 | 無 |
[讀未提交]
其他事務和非事務都能讀取事務A更改的中間數據。
[讀已提交]
寫並不會阻塞讀,只不過讀的是當前數據庫的值。
[可重複讀]
RR級別中,通過以樂觀鎖爲基礎的MVCC機制(多版本併發控制),雖然讓數據變得可重複讀,但我們讀到的數據可能是歷史數據,不是數據庫當前的數據。
一句話總結:在同一個事務內的查詢都是事務開始時刻一致的。
[實際情況,RR級別不存在幻讀]
mysql的InnoDB通過行鎖和GAP鎖結合形成的Next-Key鎖解決了RR級別時的幻讀問題。
[Next-Key鎖]
行鎖防止別的事務修改或刪除,GAP鎖防止別的事務新增,行鎖和GAP鎖結合形成的的Next-Key鎖。
[所謂阻塞,是阻塞到什麼時候?]
例如:事務A:寫(10s)讀(1s),B:讀(1s)寫(2s)。
執行:先後開啓A、B事務,然後A執行寫;在A執行寫的後立即執行B所有操作,B的寫會被阻塞。注意是阻塞到A的commit爲止,而不是A的寫執行完,A在讀(1s)時,B的寫還會被阻塞。
(名字:Gap鎖:間隙鎖。Next-Key Lock:後碼鎖Record Lock:行鎖、記錄鎖。)
1.InnoDB三種行鎖定:行鎖(Record Lock)、間隙鎖(Gap Lock)、Next-Key Lock 。
2.行鎖鎖定的是索引記錄,而不是行數據,也就是說鎖定的是key。
3.Next-Key Lock =行鎖和間隙鎖。
4. InnoDB通過行鎖和間隙鎖結合形成的Next-Key鎖解決了RR級別時的幻讀問題。
5. 間隙鎖(Gap Lock)一般是針對非唯一索引而言。
6.Gap鎖只會阻塞insert操作。(因爲最近的索引間隙裏是沒有數據的,也不可能鎖其他操作)
7.鎖間隙,是鎖的索引的間隙,左閉右開。
8.Next-Key Lock:先加行鎖再加間隙鎖。
9.可以手動給sql加共享鎖或者排它鎖。
select * from t1 where b=3 forupdate#加排他鎖X
select * from db1.t1 where b=3 lock in share mode;#加共享鎖S
10. 使用next-key lock的必備條件:
1.RR級別或以上
2.innodb_locks_unsafe_for_binlog的默認值0沒有更改。
3.非唯一索引。
11. 如果更新沒走索引,會加表鎖。走非唯一索引會加Next-Key Lock。走唯一索引加行鎖。解釋:索引唯一,InnoDB會把鎖降級成Record Lock。
12.
鎖按照精度分爲:行鎖、表鎖、意向鎖。
https://blog.csdn.net/claram/article/details/54023216(待看)
Mysql加鎖詳解:http://hedengcheng.com/?p=771
因爲如果測試數據較少的話,可能優化器直接走全表掃描,那就導致鎖住所有記錄,無法模擬出Gap鎖。