MySQL基礎系列 鎖

2021-10-09 01:12:10 字數 3217 閱讀 6936

計算機協調多個程序或執行緒併發訪問計算機資源的機制,鎖保證資料併發訪問的一致性,有效性,鎖衝突也是影響資料庫併發訪問效能的乙個重要因素,鎖是mysql在伺服器層和儲存引擎層的併發控制.

加鎖是消耗資源的,鎖的相關操作:獲得鎖,檢測鎖是否解除,釋放鎖

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

每次取資料時,認為其他事務不會修改,所以不會上鎖,但是,在更新時會判斷其他事務是否更新這個資料,可以使用版本號等機制,樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量

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

每次取資料都認為其他事務會修改資料,因此,每次取資料都會加鎖,其他事務取資料時會出現阻塞,直到獲取鎖,即行鎖,表鎖,讀鎖,寫鎖

flush tables with read lock(ftwrl)

對整個資料庫加鎖,加全域性鎖後的資料庫處於唯讀狀態,所有改變資料的操作(增,刪,改)均無法進行,被阻塞

應用場景:全庫邏輯備份

風險:主庫備份,備份期間,所有資料庫相關業務(curd)無法正常使用;

從庫備份,備份期間,無法從主庫同步binlog,主從延遲;

官方邏輯備份工具mysqldump使用–single-transaction時,會啟動乙個事務,確保拿到一致性檢視,多版本併發控制(mvcc),保證備份過程資料正常更新.

全庫唯讀不使用:set global readonly=true

原因:某些系統中,readonly的值會被用於做其他邏輯,如判斷主備庫,修改global變數的方式影響過大

異常處理差異,如果執行ftwrl命令之後,若客戶端發生異常斷開,mysql會自動釋放全域性鎖,整個庫回到正常更新的狀態,若整個庫設定為readonly後,若客戶端發生異常,資料庫一直保持readonly狀態,導致整個庫長期處於不可寫狀態,風險較高

預設情況,表鎖和行鎖是自動獲得,無需額外命令

特殊情況下,使用者需要明確進行鎖表或者進行事務控制,保證整個事務的完整性,需要使用事務控制和鎖定語句完成.

加鎖:lock tables talbe-name read

lock tables talbe-name write

取消鎖:

unlock tables

客戶端斷開時,自動釋放鎖

lock tables限制其他執行緒的讀寫,同時顯示本執行緒的其他操作物件

innodb支援行級鎖,一般不使用lock tables控制併發,鎖住全表,影響較大

表共享讀鎖(table read lock),不會阻塞其他使用者對同一表的讀請求,但會阻塞對同一表的寫請求;

表獨佔寫鎖(table write lock),會阻塞其他使用者對同一表的讀和寫操作;

預設情況下,寫鎖比讀鎖優先順序更高,當乙個鎖釋放時,這個鎖會優先給寫鎖佇列中等候的獲取鎖請求,然後再給讀鎖佇列中等候的獲取鎖請求.

無需顯式使用,訪問乙個表時會自動加上

保證讀寫的正確性

加mdl鎖的情況:

對錶做增刪改查操作

當變更表結構

讀鎖之間不互斥,寫鎖之間互斥

mdl當事務提交才會釋放

變更表結構時,會鎖住資料的查詢和更新操作,小心處理

共享鎖:允許乙個事務讀取一行,阻止其他事務獲取相同的資料集的排它鎖;

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

意向鎖:實現行鎖和表鎖共存

意向共享鎖:事務給資料行加行共享鎖,事務給資料行加共享鎖前必須先獲得該錶的意向共享鎖

意向排它鎖:事務給資料行加排它鎖,事務給資料行加排它鎖前,必須先獲得該錶的意向排它鎖

使用範圍條件,不使用相等條件檢索資料,並請求共享或排他鎖時,innodb會給符合條件的已有資料索引項加鎖,對於鍵值在條件範圍內但不存在的記錄,稱為"間隙",innodb對間隙加鎖,即間隙鎖(next-key lock)

使用範圍條件檢索並鎖定記錄時,innodb加鎖機制會阻塞符合條件範圍內鍵值的併發插入,造成嚴重的鎖等待,因此實際場景中,尤其是併發插入較多的應用,盡量優化業務邏輯,用相等條件更新資料,避免使用範圍條件

作用:防止幻讀,滿足相關隔離級別的要求

滿足恢復和複製需要

innodb:

意向鎖是innodb自動加的,無需使用者干預

update,delet,insert自動新增排它鎖

普通select,innodb不加任何鎖

事務可以通過語句顯式地給記錄集新增共享鎖或排它鎖:

共享鎖:select * from table-name where sentences lock in share mode

其他事務可以查詢該記錄,並且可以對該記錄新增share mode的共享鎖,如果當前事務需要對失去進行更新,會出現死鎖

解析:將查詢到的資料加上乙個share鎖,表示其他事務只能對這些資料進行簡單的select操作,並不能進行dml操作

應用場景:確保查到的資料沒有被其他事務正在修改,即確保查到的資料是最新的資料,並且不允許其他人修改資料,但自己同樣不一定能修改資料,其他事務可能同樣使用了共享鎖

排它鎖:select * from table-name where sentences for update,其他事務可以查詢該記錄,不能對該記錄新增共享鎖或排他鎖,而是獲得等待獲得鎖

解析:相當於update效果,查詢時,將對應索引查詢的資料加排它鎖

應用場景:保證自己查到的資料是最新資料,並且查到的資料只允許自己修改

相互持有鎖,等待對方釋放

事務a:持有id=2的寫鎖,修改id=1的資料

事務b:持有id=1的寫鎖,修改id=2的資料

a等待b釋放id=1的寫鎖,

b等待a釋放id=2的寫鎖

相互等待,無法釋放,

避免死鎖方案:

事務開始時,通過為預期要修改的行使用select *** for update,獲取必要的鎖,使這些行的更改語句在該操作之後執行的

事務中,如果要更新記錄,應該直接申請足夠級別的鎖,即排它鎖,而不應該申請共享鎖或更新時再申請排它鎖,因為這時當使用者再申請排它鎖是,其他事務可能已經獲取相同記錄的共享鎖,造成鎖衝突,甚至死鎖

如果事務需要修改或鎖定多個表,應該在每個事務中以相同的順序使用加鎖語句,應用中,如果不同的程式會併發訪問多個表,應盡量約定以相同的順序來訪問表,降低死鎖機會

通過select *** lock in share mode獲取行的讀鎖後,如果當前事務再需要對該記錄進行更新操作,可能造成死鎖

改變事務隔離級別

排他意向共享

意向排他

【參考文獻】

[1][2]

MySQL系列之鎖

分布式鎖 疑問?什麼是共享鎖?共享鎖 共享讀鎖,排他鎖 獨佔寫鎖 鎖機制與innodb鎖演算法 在關係型資料庫中,可以按照鎖的粒度把資料庫鎖分為行級鎖 innodb引擎 表級鎖 myisam引擎 和頁級鎖 bdb引擎 myisam採用表級鎖 table level locking innodb支援行...

Mysql系列之鎖機制

一般乙個程式滿,從消耗的角度,乙個是cpu,乙個是io,但有的時候mysql慢,是因為某條sql不小心把整個表給鎖了。鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。在資料庫中,除了傳統的計算機資源 如cpu,ram,i o 的爭用外,資料也是供很多使用者共享的資源。如何保證資料併發訪問的一致...

mysql筆記系列 五 全域性鎖,表鎖,行鎖

資料庫的鎖 分為 全域性鎖,表級鎖,行鎖 1.1 全域性鎖 就是給整個資料庫加鎖,mysql提供了乙個命令為 flush tables with read lock 使用後 整個庫都將處於唯讀狀態 其他執行緒的 資料更新操作 增刪改 資料定義語句 建表,修改表結構 和更新類事務的提交語句 都阻塞。全...