加薪大法之資料庫鎖,學會了工資又能多2k

****對於資料庫鎖不懂的小夥伴可以諮詢我,分享連結[https://note。youdao。com/s/SJX3wYwk]****

提示:這張大圖已經很詳細清晰的記錄了資料庫鎖的功能和注意事項等,不懂可以問我哦

鎖在 MySQL 中是非常重要的一部分,鎖對 MySQL 的資料訪問併發有著舉足輕重的影響。鎖涉及到的知識篇幅也很多,所以要啃完並消化到自己的肚子裡,是需要靜下心好好反反覆覆幾遍地細細品味。本文是對鎖的一個大概的整理,一些相關深入的細節,還是需要找到相關書籍來繼續夯實。

————————————————

加薪大法之資料庫鎖,學會了工資又能多2k

鎖的認識

1。1 鎖的解釋

計算機協調多個程序或執行緒併發訪問某一資源的機制。

1。2 鎖的重要性

在資料庫中,除傳統計算資源(CPU、RAM、I\O等)的爭搶,資料也是一種供多使用者共享的資源。

如何保證資料併發訪問的一致性,有效性,是所有資料庫必須要解決的問題。

鎖衝突也是影響資料庫併發訪問效能的一個重要因素,因此鎖對資料庫尤其重要。

1。3 鎖的缺點

加鎖是消耗資源的,鎖的各種操作,包括獲得鎖、檢測鎖是否已解除、釋放鎖等 ,都會增加系統的開銷。

1。4 簡單的例子

現如今網購已經特別普遍了,比如淘寶雙十一活動,當天的人流量是千萬及億級別的,但商家的庫存是有限的。

系統為了保證商家的商品庫存不發生超賣現象,會對商品的庫存進行鎖控制。當有使用者正在下單某款商品最後一件時,

系統會立馬對該件商品進行鎖定,防止其他使用者也重複下單,直到支付動作完成才會釋放(支付成功則立即減庫存售罄,支付失敗則立即釋放)。

鎖的型別

2。1 表鎖

種類

讀鎖(read lock),也叫共享鎖(shared lock)

針對同一份資料,多個讀操作可以同時進行而不會互相影響(select)

寫鎖(write lock),也叫排他鎖(exclusive lock)

當前操作沒完成之前,會阻塞其它讀和寫操作(update、insert、delete)

儲存引擎預設鎖

MyISAM

特點

1。 對整張表加鎖

2。 開銷小

3。 加鎖快

4。 無死鎖

5。 鎖粒度大,發生鎖衝突機率大,併發性低

結論

1。 讀鎖會阻塞寫操作,不會阻塞讀操作

2。 寫鎖會阻塞讀和寫操作

建議

MyISAM的讀寫鎖排程是寫優先,這也是MyISAM不適合做寫為主表的引擎,因為寫鎖以後,其它執行緒不能做任何操作,大量的更新使查詢很難得到鎖,從而造成永遠阻塞。

2。2 行鎖

種類

讀鎖(read lock),也叫共享鎖(shared lock)

允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖

寫鎖(write lock),也叫排他鎖(exclusive lock)

允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享鎖和排他鎖

意向共享鎖(IS)

一個事務給一個數據行加共享鎖時,必須先獲得表的IS鎖

意向排它鎖(IX)

一個事務給一個數據行加排他鎖時,必須先獲得該表的IX鎖

儲存引擎預設鎖

InnoDB

特點

1。 對一行資料加鎖

2。 開銷大

3。 加鎖慢

4。 會出現死鎖

5。 鎖粒度小,發生鎖衝突機率最低,併發性高

事務併發帶來的問題

1。 更新丟失

解決:讓事務變成序列操作,而不是併發的操作,即對每個事務開始——-對讀取記錄加排他鎖

2。 髒讀

解決:隔離級別為Read uncommitted

3。 不可重讀

解決:使用Next-Key Lock演算法來避免

4。 幻讀

解決:間隙鎖(Gap Lock)

2。3 頁鎖

開銷、加鎖時間和鎖粒度介於表鎖和行鎖之間,會出現死鎖,併發處理能力一般(此鎖不做多介紹)

如何上鎖?

3。1 表鎖

隱式上鎖(預設,自動加鎖自動釋放)

select //上讀鎖

insert、update、delete //上寫鎖

顯式上鎖(手動)

lock table tableName read;//讀鎖

lock table tableName write;//寫鎖

解鎖(手動)

unlock tables;//所有鎖表

session01 session02

lock table teacher read;// 上讀鎖

select * from teacher; // 可以正常讀取 select * from teacher;// 可以正常讀取

update teacher set name = 3 where id =2;// 報錯因被上讀鎖不能寫操作 update teacher set name = 3 where id =2;// 被阻塞

unlock tables;// 解鎖

update teacher set name = 3 where id =2;// 更新操作成功

session01 session02

lock table teacher write;// 上寫鎖

select * from teacher; // 可以正常讀取 select * from teacher;// 被阻塞

update teacher set name = 3 where id =2;// 可以正常更新操作 update teacher set name = 4 where id =2;// 被阻塞

unlock tables;// 解鎖

select * from teacher;// 讀取成功

update teacher set name = 4 where id =2;// 更新操作成功

3。2 行鎖

隱式上鎖(預設,自動加鎖自動釋放)

select //不會上鎖

insert、update、delete //上寫鎖

顯式上鎖(手動)

select * from tableName lock in share mode;//讀鎖

select * from tableName for update;//寫鎖

解鎖(手動)

1。 提交事務(commit)

2。 回滾事務(rollback)

3。 kill 阻塞程序

session01 session02

begin;

select * from teacher where id = 2 lock in share mode;// 上讀鎖

select * from teacher where id = 2;// 可以正常讀取

update teacher set name = 3 where id =2;// 可以更新操作 update teacher set name = 5 where id =2;// 被阻塞

commit;

update teacher set name = 5 where id =2;// 更新操作成功

session01 session02

begin;

select * from teacher where id = 2 for update;// 上寫鎖

select * from teacher where id = 2;// 可以正常讀取

update teacher set name = 3 where id =2;// 可以更新操作 update teacher set name = 5 where id =2;// 被阻塞

rollback;

update teacher set name = 5 where id =2;// 更新操作成功

為什麼上了寫鎖,別的事務還可以讀操作?

因為InnoDB有MVCC機制(多版本併發控制),可以使用快照讀,而不會被阻塞。

行鎖的實現演算法

4。1 Record Lock 鎖

單個行記錄上的鎖

Record Lock總是會去鎖住索引記錄,如果InnoDB儲存引擎表建立的時候沒有設定任何一個索引,這時InnoDB儲存引擎會使用隱式的主鍵來進行鎖定

4。2 Gap Lock 鎖

當我們用範圍條件而不是相等條件檢索資料,並請求共享或排他鎖時,InnoDB會給符合條件的已有資料記錄的索引加鎖,對於鍵值在條件範圍內但並不存在的記錄。

優點:解決了事務併發的幻讀問題

不足:因為query執行過程中透過範圍查詢的話,他會鎖定爭個範圍內所有的索引鍵值,即使這個鍵值並不存在。

間隙鎖有一個致命的弱點,就是當鎖定一個範圍鍵值之後,即使某些不存在的鍵值也會被無辜的鎖定,而造成鎖定的時候無法插入鎖定鍵值範圍內任何資料。在某些場景下這可能會對效能造成很大的危害。

4。3 Next-key Lock 鎖

同時鎖住資料+間隙鎖

在Repeatable Read隔離級別下,Next-key Lock 演算法是預設的行記錄鎖定演算法。

4。4 行鎖的注意點

1。 只有透過索引條件檢索資料時,InnoDB才會使用行級鎖,否則會使用表級鎖(索引失效,行鎖變表鎖)

2。 即使是訪問不同行的記錄,如果使用的是相同的索引鍵,會發生鎖衝突

3。 如果資料表建有多個索引時,可以透過不同的索引鎖定不同的行

如何排查鎖?

5。1 表鎖

查看錶鎖情況

show open tables;

表鎖分析

show status like ‘table%’;

1。 table_locks_waited

出現表級鎖定爭用而發生等待的次數(不能立即獲取鎖的次數,每等待一次值加1),此值高說明存在著較嚴重的表級鎖爭用情況

2。 table_locks_immediate

產生表級鎖定次數,不是可以立即獲取鎖的查詢次數,每立即獲取鎖加1

5。2 行鎖

行鎖分析

show status like ‘innodb_row_lock%’;

1。 innodb_row_lock_current_waits //當前正在等待鎖定的數量

2。 innodb_row_lock_time //從系統啟動到現在鎖定總時間長度

3。 innodb_row_lock_time_avg //每次等待所花平均時間

4。 innodb_row_lock_time_max //從系統啟動到現在等待最長的一次所花時間

5。 innodb_row_lock_waits //系統啟動後到現在總共等待的次數

information_schema 庫

1。 innodb_lock_waits表

2。 innodb_locks表

3。 innodb_trx表

最佳化建議

1。 儘可能讓所有資料檢索都透過索引來完成,避免無索引行鎖升級為表鎖

2。 合理設計索引,儘量縮小鎖的範圍

3。 儘可能較少檢索條件,避免間隙鎖

4。 儘量控制事務大小,減少鎖定資源量和時間長度

5。 儘可能低級別事務隔離

死鎖

6。1 解釋

指兩個或者多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性迴圈的現象

6。2 產生的條件

1。 互斥條件:一個資源每次只能被一個程序使用

2。 請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放

3。 不剝奪條件:程序已獲得的資源,在沒有使用完之前,不能強行剝奪

4。 迴圈等待條件:多個程序之間形成的一種互相迴圈等待的資源的關係

6。1 解決

1。 檢視死鎖:show engine innodb status \G

2。 自動檢測機制,超時自動回滾代價較小的事務(innodb_lock_wait_timeout 預設50s)

3。 人為解決,kill阻塞程序(show processlist)

4。 wait for graph 等待圖(主動檢測)

6。1 如何避免

1。 加鎖順序一致,儘可能一次性鎖定所需的資料行

2。 儘量基於primary(主鍵)或unique key更新資料

3。 單次操作資料量不宜過多,涉及表儘量少

4。 減少表上索引,減少鎖定資源

5。 儘量使用較低的隔離級別

6。 儘量使用相同條件訪問資料,這樣可以避免間隙鎖對併發的插入影響

7。 精心設計索引,儘量使用索引訪問資料

8。 藉助相關工具:pt-deadlock-logger

樂觀鎖與悲觀鎖

7。1 悲觀鎖

解釋

假定會發生併發衝突,遮蔽一切可能違反資料完整性的操作

實現機制

表鎖、行鎖等

實現層面

資料庫本身

適用場景

併發量大

7。2 樂觀鎖

解釋

假設不會發生併發衝突,只在提交操作時檢查是否違反資料完整性

實現機制

提交更新時檢查版本號或者時間戳是否符合

實現層面

業務程式碼

適用場景

併發量小

————————————————

原文作者:zhangdeTalk

轉自連結:https://learnku。com/articles/39212

版權宣告:著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請保留以上作者資訊和原文連結。