mysql 共享锁_mysql有排他锁为什么还需要共享锁呢?
兩把鎖缺一不可,InnoDB 引擎中的四種隔離級別就是用 排他鎖 + 共享鎖 實現的。
下面是個人理解,可能并不嚴謹。
首先說一下并發可能產生的四種問題,如果你還不了解這四個問題,最好拿至少 20 分鐘時間模擬一下場景。
假設有兩個事務A,B,有一個資源值(一條記錄)是V;另外一個資源值(多條記錄的集合) VVV。
1.丟失修改:A 修改 V 為 v1, B 修改 V 為 v2。那么最后 V 是v1 還是 v2 呢?無論結果是什么,一定只有一個結果,那么另外一個修改就丟失了,因此叫做丟失修改。
2.臟讀:A 修改 V 為 v1, 但是修改不成功,事務會回滾。 在事務 A 回滾的時候,B去讀取 V 的值,讀到的值是什么? 是 v1。 我們的 B 事務想期望的值是 V, 但是卻讀到了 v1,v1是一個臟數據,因此我們簡稱臟讀。
3.不可重復讀:這個場景下,A 事務要讀兩次 V 的值。 第一次直接讀取,然后停下,這個時候 B 事務去修改 V 的值為 v1,然后 A 事務再執行它的第二次讀取。第一次讀到的是 V, 第二次讀到的是 v1,一個事務不同時間讀到的值不一樣,這個就是不可重復讀。
4.幻讀:這個場景的資源值不再是一個記錄了,而是很多記錄的一個集合,我們叫它 VVV(假設有三條記錄,分別為 v1,v2,v3)。A 事務讀到了 VVV 集合,再使用它之前,B 事務把集合中的 v3 值刪除了,這個時候我們去使用這個集合中的 v3, 但是發現值不在這里了,我們所讀到的集合就是一個不真實的集合。幻讀的資源一定要是一個集合,修改(刪除也被認為是一種修改)會導致集合變化。
針對這四種問題,MySQL有四種不同的隔離級別,不同的隔離級別解決的問題不一樣。
1.讀未提交:解決丟失修改的問題。由上面可知,兩個事務同時修改一個資源值的時候,會發生修改丟失的問題。這個時候我們對資源加一個排他鎖,加鎖以后,資源只能由一個事務所擁有,修改完畢以后另外一個事務才可以拿到資源。這就解決了丟失修改的問題。(資源值加 X 鎖,事務結束釋放)。
2.讀提交:解決臟讀問題。在 1 的基礎上(給資源加 X 鎖,直到事務結束),增加一個 S 鎖。 讀數據的時候給數據加一個 S 鎖, 資源在有 X 鎖的時候,S 鎖是加不上去的,因此直到事務結束, S 鎖才可以加上去, 事務都結束了,自然不會讀到臟數據。(寫數據加 X 鎖,事務結束釋放,讀數據加 S 鎖,讀完數據立即釋放)
3.可重復讀:上一個隔離級別中,讀的時候加 S 鎖。 在不可重復讀的問題里面:
a.第一次讀,加 S 鎖,得到 V,釋放 S 鎖;
b. 然后 B 事務修改 V 為 v1,加了 X 鎖,事務結束后釋放;
c.第二次讀,加 S 鎖,得到 v1,釋放 S 鎖。
是不是不可重復的問題還是存在?怎么解決呢? 將我們的 S 鎖設定為,一個事務結束后才釋放。 加了這個限定條件以后, B 事務就無法修改 V, 因為 V 現在加了 S 鎖,只能被讀,無法被修改。(寫數據加 X 鎖,事務結束釋放,讀數據加 S 鎖,事務結束釋放)
4.串行化,串行化是事務完全按照 ACID 的四個原則來執行,這種情況效率比較低,很少用。
這樣一說了,你覺得共享鎖還是多余的嗎?
各位姥爺,能理解的點個贊啊。
再針對具體問題做一個解釋。
select *from table_name for update; // 加 X 鎖
select *from table_name for share; // 加 S 鎖,MySQL 版本 8.0 以后。
select *from table_name lock in share mode; 加 S 鎖, MySQL 版本 8.0 以前。
示例: 1. 首先開始一個事務A,并且關閉自動提交。
START TRANSACTION;
set autocommit = 0;
2. 然后在查詢條件下加一把 X 鎖
SELECT*FROM table_name for UPDATE;
3. 接下來你再開一個查詢窗口,開不開事務都沒關系,給查詢加一把 S 鎖
SELECT *FROM person LOCK IN SHARE MODE; // 我的版本是 MySQL 5.6
執行這條查詢 SQL 的時候,就會被堵塞。原因是你在 事務A 中給表加了 X 鎖,再給表加 S 鎖的時候就會堵塞。
當然,你可以先加 S 鎖,再去加 X 鎖的時候同樣會被堵塞。
希望看明白了可以點個贊。
總結
以上是生活随笔為你收集整理的mysql 共享锁_mysql有排他锁为什么还需要共享锁呢?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java坐标移动题目case_用java
- 下一篇: linux cmake编译源码,linu