MySQL中的全域性鎖和表級鎖

2021-10-06 05:12:35 字數 2054 閱讀 1857

資料庫鎖設計的初衷是解決併發出現的一些問題。當出現併發訪問的時候,資料庫需要合理的控制資源的訪問規則。而鎖就是訪問規則的重要資料結構。

根據鎖的範圍,分為全域性鎖、表級鎖和行級鎖三類。

全域性鎖就是對整個資料庫例項加鎖。mysql提供而乙個全域性讀鎖的方法。命令是

flush tables

with

read

lock

當你需要讓整個庫處於唯讀的狀態時,可以使用這個命令,之後其他執行緒的資料更新語句、資料定義語句(建表、修改表等)和更新事務的提交語句等都會被阻塞。

全域性表的典型使用場景是作為全域性邏輯備份

也就是把整個庫的每個表都 select出來 存成文字。以前的做法是通過執行宣告的語句確保不會有其他執行緒對資料庫做更新操作,然後對整個庫做備份。注意,在備份過程中整個庫完全處於唯讀狀態。

看來加全域性鎖問題會很多,其實備份為什麼要加鎖呢?

如果不加鎖會產生哪些問題?

在支付的場景下,生成訂單和扣款兩個操作是有先後順序的。如果是先備份賬戶餘額表再生成訂單表, 中間的這個時間段可能會出現一些問題,如果賬戶餘額已經扣了但是生成訂單表失敗,那麼使用者會看到自己已經付款了但是還沒有生成訂單資訊。也就是說不加鎖的情況下備份系統得到的資料庫不是乙個邏輯時間點,檢視的邏輯不一致。

既然要讀全庫,為什麼不使用set global readonly = true的方式呢?

確實readonly也可以讓錢庫進入唯讀狀態,但是建議使用

flush tables

with

read

lock

主要原因有兩個:

業務的更新不只是增刪改資料(dml),還有可能是加字段等修改表結構的操作(ddl)。不論是哪種方法,乙個庫被全域性鎖上後,你要對立面的任何乙個表做加字段的操作,都是會被鎖住的。

但是即使沒有被全域性鎖住,加字段也不是就能一帆風順的,因為你還會碰上表級鎖。

mysql表級別的鎖有兩種:一種是表鎖,一種是元資料鎖(mdl)

因此在5.5版本裡面引入了元資料鎖,當對於乙個表做增刪改查的時候,加mdl讀鎖;當要對錶結構做變更操作的時候加mdl寫鎖。

下面需要注意的是

sessiona先啟動,這時候會對錶 t 加乙個mdl讀鎖。由於sessionb需要的也是讀鎖因此可以正常執行。

但是sessionc會被阻塞,因為sessionc是需要寫鎖的,讀鎖和寫鎖之間是會被阻塞的。

這時候後面又來了sessiond,sessiond需要讀鎖,但是前面的sessionc還沒獲取到寫鎖所以一直阻塞到那裡,他也跟著阻塞。如果某個表上的查詢語句很頻繁,而且客戶端有重試機制,也就是說超時後會再起乙個新的session請求,這樣整個庫的執行緒就會被堆滿。

解決方法:

在mysql的information_schema庫的innodb_trx表中,你可以查到當前執行中的事務。如果你要做ddl變更的表,剛好有長事務在執行,要考慮先暫停ddl,或者直接kill掉事務。

如果更新表的請求很頻繁的話,kill未必管用,因為新的請求會很快到來。比較理想的機制是,在alter table語句裡面設定等待時間,如果超過了這個時間就先放棄不在阻塞,之後開發人員再重試這個命令。

mariadb乙個資料庫引擎已經合併了alisql的這個功能,所以這兩個開源分支目前都支援ddl,設定等待時間的語法。

alter

table tbl_name nowait add

column..

.alter

table tbl_name wait n add

column..

.

MySQL全域性鎖和表鎖

對整個資料庫加鎖,語句為 flush tables with read lock ftwrl 加鎖之後不可以進行增刪改,也不能做ddl,是乙個整庫唯讀的狀態,一般只有在做全庫邏輯備份時才需要全域性鎖。可以看到,如果採用這種方式對庫加鎖的話,雖然保證了一致性,但十分影響業務。所以,應該盡量少採用這種方...

151 全域性鎖 表級鎖

對整個庫例項加鎖。讓整個庫處於唯讀狀態的時候,可以使用這個命令,之後其他執行緒的以下語句會被阻塞 增刪改 建表 修改表結 更新類事務的提交 mysql 提供了乙個加全域性讀鎖的方法,命令是flush tables with read lock ftwrl 用unlock tables主動釋放鎖,也可...

mysql 4 1 全域性鎖 表鎖 行級鎖

描述 兩階段鎖協議 行鎖是在需要的時候才加上的,但並不是不需要了就立刻釋放,而是要等到事務結束時才釋放 行鎖針對資料表中行記錄的鎖 死鎖當併發系統中不同執行緒出現迴圈資源依賴,涉及的執行緒都在等待別的執行緒釋放資源時,就會導致這幾個執行緒都進入無限等待的狀態 根據加鎖的範圍,mysql 裡面的鎖大致...