資料庫(七) MySQL鎖機制

2021-10-06 13:24:14 字數 4619 閱讀 5547

資料庫的樂觀鎖和悲觀鎖?

mysql 中有哪幾種鎖,列舉一下?

mysql中innodb引擎的行鎖是怎麼實現的?

mysql 間隙鎖有沒有了解,死鎖有沒有了解,寫一段會造成死鎖的 sql 語句,死鎖發生了如何解決,mysql 有沒有提供什麼機制去解決死鎖

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

在資料庫中,除傳統的計算資源(如cpu、ram、i/o等)的爭用以外,資料也是一種供許多使用者共享的資源。資料庫鎖定機制簡單來說,就是資料庫為了保證資料的一致性,而使各種共享資源在被併發訪問變得有序所設計的一種規則。

打個比方,我們到**上買一件商品,商品只有一件庫存,這個時候如果還有另乙個人買,那麼如何解決是你買到還是另乙個人買到的問題?這裡肯定要用到事物,我們先從庫存表中取出物品數量,然後插入訂單,付款後插入付款表資訊,然後更新商品數量。在這個過程中,使用鎖可以對有限的資源進行保護,解決隔離和併發的矛盾。

鎖的分類

從對資料操作的型別分類:

從對資料操作的粒度分類:

為了盡可能提高資料庫的併發度,每次鎖定的資料範圍越小越好,理論上每次只鎖定當前操作的資料的方案會得到最大的併發度,但是管理鎖是很耗資源的事情(涉及獲取,檢查,釋放鎖等動作),因此資料庫系統需要在高併發響應和系統效能兩方面進行平衡,這樣就產生了「鎖粒度(lock granularity)」的概念。 行鎖

表鎖頁鎖

myisam

√bdb√√

innodb√√

memory

myisam 表鎖

myisam 的表鎖有兩種模式:

myisam 表的讀操作與寫操作之間,以及寫操作之間是序列的。當乙個執行緒獲得對乙個表的寫鎖後, 只有持有鎖的執行緒可以對錶進行更新操作。其他執行緒的讀、 寫操作都會等待,直到鎖被釋放為止。

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

innodb 行鎖

innodb 實現了以下兩種型別的行鎖:

為了允許行鎖和表鎖共存,實現多粒度鎖機制,innodb 還有兩種內部使用的意向鎖(intention locks),這兩種意向鎖都是表鎖:

索引失效會導致行鎖變表鎖。比如 vchar 查詢不寫單引號的情況。

加鎖機制

樂觀鎖與悲觀鎖是兩種併發控制的思想,可用於解決丟失更新問題

樂觀鎖會「樂觀地」假定大概率不會發生併發更新衝突,訪問、處理資料過程中不加鎖,只在更新資料時再根據版本號或時間戳判斷是否有衝突,有則處理,無則提交事務。用資料版本(version)記錄機制實現,這是樂觀鎖最常用的一種實現方式

悲觀鎖會「悲觀地」假定大概率會發生併發更新衝突,訪問、處理資料前就加排他鎖,在整個資料處理過程中鎖定資料,事務提交或回滾後才釋放鎖。另外與樂觀鎖相對應的,悲觀鎖是由資料庫自己實現了的,要用的時候,我們直接呼叫資料庫的相關語句就可以了。

鎖模式(innodb有三種行鎖的演算法)

select

*from

table

where id =

1for

update

;

它會在 id=1 的記錄上加上記錄鎖,以阻止其他事務插入,更新,刪除 id=1 這一行

在通過 主鍵索引 與 唯一索引 對資料行進行 update 操作時,也會對該行資料加記錄鎖:

-- id 列為主鍵列或唯一索引列

update

set age =

50where id =

1;

innodb 也會對這個「間隙」加鎖,這種鎖機制就是所謂的間隙鎖。

對索引項之間的「間隙」加鎖,鎖定記錄的範圍(對第一條記錄前的間隙或最後一條將記錄後的間隙加鎖),不包含索引項本身。其他事務不能在鎖範圍內插入資料,這樣就防止了別的事務新增幻影行。

間隙鎖基於非唯一索引,它鎖定一段範圍內的索引記錄。間隙鎖基於下面將會提到的next-key locking 演算法,請務必牢記:使用間隙鎖鎖住的是乙個區間,而不僅僅是這個區間中的每一條資料。

select

*from

table

where id betwen 1

and10

forupdate

;

即所有在(1,10)區間內的記錄行都會被鎖住,所有id 為 2、3、4、5、6、7、8、9 的資料行的插入會被阻塞,但是 1 和 10 兩條記錄行並不會被鎖住。

gap鎖的目的,是為了防止同一事務的兩次當前讀,出現幻讀的情況

next-key 可以理解為一種特殊的間隙鎖,也可以理解為一種特殊的演算法。通過臨建鎖可以解決幻讀的問題。每個資料行上的非唯一索引列上都會存在一把臨鍵鎖,當某個事務持有該資料行的臨鍵鎖時,會鎖住一段左開右閉區間的資料。需要強調的一點是,innodb 中行級鎖是基於索引實現的,臨鍵鎖只與非唯一索引列有關,在唯一索引列(包括主鍵列)上不存在臨鍵鎖。

對於行的查詢,都是採用該方法,主要目的是解決幻讀的問題。

對於行的查詢,都是採用該方法,主要目的是解決幻讀的問題。

for update 僅適用於innodb,且必須在事務塊(begin/commit)中才能生效。在進行事務操作時,通過「for update」語句,mysql會對查詢結果集中每行資料都新增排他鎖,其他執行緒對該記錄的更新與刪除操作都會阻塞。排他鎖包含行鎖、表鎖。

innodb這種行鎖實現特點意味著:只有通過索引條件檢索資料,innodb才使用行級鎖,否則,innodb將使用表鎖!假設有個表單 products ,裡面有id跟name二個字段,id是主鍵。

select

*from products where id=

'3'for

update

;select

*from products where id=

'3'and

type=1

forupdate

;

select

*from products where id=

'-1'

forupdate

;

select

*from products where name=

'mouse'

forupdate

;

select

*from products where id<>

'3'for

update

;

select

*from products where id like

'3'for

update

;

注1: for update僅適用於innodb,且必須在交易區塊(begin/commit)中才能生效。

注2: 要測試鎖定的狀況,可以利用mysql的command mode ,開二個視窗來做測試。

mysql 遇到過死鎖問題嗎,你是如何解決的?

死鎖

死鎖產生:

檢測死鎖:資料庫系統實現了各種死鎖檢測和死鎖超時的機制。innodb儲存引擎能檢測到死鎖的迴圈依賴並立即返回乙個錯誤。

死鎖恢復:死鎖發生以後,只有部分或完全回滾其中乙個事務,才能打破死鎖,innodb目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾。所以事務型應用程式在設計時必須考慮如何處理死鎖,多數情況下只需要重新執行因死鎖回滾的事務即可。

外部鎖的死鎖檢測:發生死鎖後,innodb 一般都能自動檢測到,並使乙個事務釋放鎖並回退,另乙個事務獲得鎖,繼續完成事務。但在涉及外部鎖,或涉及表鎖的情況下,innodb 並不能完全自動檢測到死鎖, 這需要通過設定鎖等待超時引數 innodb_lock_wait_timeout 來解決

死鎖影響效能:死鎖會影響效能而不是會產生嚴重錯誤,因為innodb會自動檢測死鎖狀況並回滾其中乙個受影響的事務。在高併發系統上,當許多執行緒等待同乙個鎖時,死鎖檢測可能導致速度變慢。有時當發生死鎖時,禁用死鎖檢測(使用innodb_deadlock_detect配置選項)可能會更有效,這時可以依賴innodb_lock_wait_timeout設定進行事務回滾。

myisam避免死鎖

innodb避免死鎖

如果出現死鎖,可以用 show engine innodb status;命令來確定最後乙個死鎖產生的原因。返回結果中包括死鎖相關事務的詳細資訊,如引發死鎖的 sql 語句,事務已經獲得的鎖,正在等待什麼鎖,以及被回滾的事務等。據此可以分析死鎖產生的原因和改進措施。

MySQL資料庫的鎖機制

原文首發於 本文出自 rebornchang的部落格 拋開資料庫引擎說資料庫鎖機制的都是流氓 引言 mysql資料庫的引擎分為三種,myisam isam innodb以及memory,具體的引擎型別效能比較可以baidu到,這裡就不多說了,本文中所說的鎖機制基於innodb引擎,那為啥說基於inn...

Mysql資料庫的鎖機制

鎖機制 當客戶端操作表 記錄 時,為了保證操作的隔離性 多個客戶端操作不能相互影響 通過加鎖來處理。操作方面 讀鎖 讀操作時增加的鎖,也叫共享鎖,s lock。特徵是所有人都只可以讀,只有釋放鎖之後才可以寫。寫鎖 寫操作時增加的鎖,也叫獨佔鎖或排他鎖,x lock。特徵,只有鎖表的客戶可以操作 讀寫...

MySQL資料庫的鎖機制

在併發訪問情況下,很有可能出現不可重複讀等等讀現象。為了更好的應對高併發,封鎖 時間戳 樂觀併發控制 樂觀鎖 悲觀併發控制 悲觀鎖 都是併發控制採用的主要技術方式。按操作劃分 dml鎖,ddl鎖 按鎖的粒度劃分 表級鎖 行級鎖 頁級鎖 按鎖級別劃分 共享鎖 排他鎖 按加鎖方式劃分 自動鎖 顯示鎖 按...