InnoDB存儲引擎實現了一下兩種標准的行級鎖:
共享鎖S LOCK 允許事務讀一行數據
排他鎖 X LOCK 允許事務刪除或更新一行數據
如果是一個事務T1斤獲得了行r的共享鎖,那么另外一個事務T2可以立即獲得行r的共享鎖,因為讀取並沒有改變行r的數據,稱這種情況為鎖兼容Lock Compatible。但若有其他事務T3想獲得行r的排他鎖,則必須等待事務T1、T2釋放行r的共享鎖---這種情況稱為鎖不兼容
可以看到 X鎖與任何鎖都不兼容,而S鎖僅和S鎖金融。需要特別注意,S和X都是行鎖,兼容是指通一行記錄row鎖的兼容情況
此外,InnoDB支持多粒度granular鎖定。這種鎖定允許事務在航級別上的鎖和表級別上的鎖同時存在。為了支持在不通粒度上進行加鎖操作,InnoDB存儲引擎支持一種額外的鎖方式,稱為意向鎖(Intention Lock)。意向鎖是將鎖定的對象分為多個層次,意向鎖意味着事務希望在更細粒度(fine granularity)上進行枷鎖。
若將上鎖的對象看成一棵樹,那么對最上層的對象上鎖,也就是對最細粒度的對象進行上鎖,那么首先需要對粗粒度的對象上鎖,如上圖,如果需要對頁上的記錄r進行上X鎖,那么分別需要對數據A、表、頁上意向鎖IX,最后對記錄r上X鎖,若其中任何一部分導致等待,那么該操作需要等待粗粒度鎖的完成,舉例來說,在對記錄r及殺死那個X鎖之前,已經有事務對表1進行了S表鎖,那么表1已存在S鎖,之后事務需要對記錄r在表上系上IX,由於不兼容,那么該事物需要等待表鎖操作的完成
InnoDB存儲引擎支持意向鎖設計比較簡練,其意向鎖即為表級別鎖。設計目的主要是為了在一個事務上揭示下一個行將別請求的鎖類型。其支持兩種意向鎖
意向共享鎖 IS LOCK 事務想要獲得一張表中某幾行的共享鎖 意向排他鎖 IX LOCK 事務想要獲得一張表中某幾行的排他鎖
由於InnoDB存儲引擎支持的是行級別的鎖,因此意向鎖其實是不會阻塞出全表掃以外的任何請求
可以通過SHOW ENGINE INNODB STATUS來查看當前鎖請求的信息
可以看到SQL語句 select * from t where a<4 lock in share mode在等待。RECODE LOCKS space id 30 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t' trx id 48B89BD lock_mode X locks rec but not gap 表示鎖住的資源。locks rec but not gap代表鎖住的是一個索引,而不是一個范圍
在InnoDB 1.0 版本之前,用戶只能通過SHOW FULL PROCESSLIST,SHOW ENGINE INNODB STATUS來查看當前數據庫中鎖的請求,然后在判斷事物鎖的情況,從InnoDB 1.0開始。在Information_schema架構下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。通過這三張表,用戶可以更方便的監控到當前事務並發分析可能存在的鎖問題。看一下INNODB_TRX結構
通過state可以觀察到trx_id為730FEE的事務當前正在運行,而trx_id為731F4的事務處於LOCK WAIT狀態,且運行的SQL語句是select * from parent lock in shar mode。該表只是顯示了當前運行的innoDB事務,並不能准確的判斷鎖的一些情況。如果需要查看鎖,還需要訪問 INNODB_LOCKS
用戶可以清楚的看到當前鎖的信息,trx_id為730FEE的事務想表parent加了一個X的行鎖。ID為7311F4的事務想表parent申請了一個S的行鎖。lock_data都是1,申請相同的資源,因此會有等待。這樣可以解析INNODB_TRX為什么一個事務的trx_state是RUNNING另一個是LOCK WAITLE
另外需要注意的是,發現lock_data並不是可信的值。例如當用戶運行一個范圍查找時,lock_data可能只返回第一行的主鍵值。與此同時,如果當前資源被鎖住了。若鎖住的頁因為InnoDB存儲引擎緩沖池的容量,導致頁從緩沖池中被刷出,則查看INNODB_LOCKS表時,該值同樣顯示為NULL。即InnoDB存儲引擎不會從磁盤進行再一次的查找
在通過INNODB_LOCKS饞看了每張表上鎖的情況后,用戶可以判斷由此引發的等待情況。當事務較小時,用戶就可以人為地、直觀地進行判斷了。但是當事務量非常大,其中鎖和等待也時常發生。這個時候就不容易判斷。但是可以通過INNODB_LOCK_WAITS可以很直觀的反應出當前事務的等待。表INNODB_LOCK_WAITS由4個字段組成
通過上述的SQL語句,用戶可以清楚的看到哪個事務阻塞了另一個事務。當然這只是給出了事務和鎖ID,如果需要,用戶可以根據表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS得到更為直觀的詳細信息。例如,用戶可以執行如下聯合查詢