macbook pro
mysql
技術內幕innodb
儲存引擎 第二版
資料庫中最大的難點:一方面需要最大程度地利用資料庫的併發訪問,另外一方面還要確保每個使用者能以一致的方式讀取和修改資料。— 因此就有了鎖的機制。
q:innodb
儲存引擎為什麼乙個鎖和多個鎖的開銷是相同。
a:lock的物件是事務,用來鎖定的是資料庫中的物件,如:表、頁、行。並且一般lock的物件僅在事務commit
或rollback
後進行釋放(不同事務隔離級別釋放的時間可能不同)。
lock
物件事務
保護資料庫內容
持續時間
整個事務過程
模式行鎖、表鎖、意向鎖
mysql
有兩種標準的行級鎖:
① 共享鎖 (s lock)允許事務讀取一行資料;
② 排它鎖 (x lock)允許事務刪除或更新一行資料
排它鎖和任何鎖都不相容,共享鎖只和共享鎖相容
mysql
為了支援多粒度鎖定:這種鎖定允許事務在行級上的鎖和表級上的鎖同時存在。
意向鎖表示方式:ix
;
舉例:如果需要對頁上的記錄r
進行上鎖,那麼分別需要對資料庫a
,表,頁 加意向鎖ix
,最後對記錄r
加x鎖
。
所以,意向鎖就是表級鎖;意向鎖不會阻塞除全表掃瞄外的其他請求。
意向鎖只會阻塞表級鎖;q: 舉例說明為什麼需要意向鎖?意向鎖,和行級鎖比較時,排他不同型別一定不相容,都是共享型別那麼意向和行鎖都相容。
a: mysql支援行級鎖:共享鎖和排它鎖;
假設事務a,對某條記錄r申請了s鎖(共享鎖),
事務b想修改表中多條資料,申請了整個表的寫鎖。
在沒有意向鎖之前,假設事務b申請成功了,那麼理論上它就可以修改表中的任意一行,這與a持有的行鎖衝突了。
資料庫需要避免這樣的衝突,就需要讓事務b的申請被阻塞,直到a釋放了鎖。
怎麼判斷是否衝突了呢?
step1: 判斷表是否已被其他事務用表鎖鎖住
step2: 判斷表中的每行是否已被行鎖鎖住。
步驟②中,這種判斷很低效。
有了意向鎖後,
step1: 判斷表是否已被其他事務用表鎖鎖住
step2: 發現表上有意向鎖,說明表中有些行被共享鎖鎖住了,因此事務b申請表的寫鎖會被阻塞。
申請意向鎖的動作是資料庫完成的,不需要用**來控制q:這裡進一步思考,假設事務b申請的是也是某行記錄,和事務a不是一行,那麼會被阻塞嗎?
a:不會,雖然事務a
,對錶加了意向鎖is,但是意向鎖和行鎖是相容的,而事務b
上的行鎖又和事務a
不是同一行,
所以不會被阻塞。 is
ixsxis
相容相容
相容不相容
ix相容
相容不相容
不相容s
相容不相容
相容不相容
x不相容
不相容不相容
不相容概念:innodb
儲存引擎通過行多版本控制的方式來讀取當前執行時間資料庫中的資料。
一致性非鎖定讀
:innodb
儲存引擎,預設配置下的,預設的讀取方式;
如果讀取的行正在執行innodb
預設的事務隔離級別:repeatable read
;
repeatable read
隔離級別採用next-key lock
演算法,避免了不可重複讀。
next-key lock演算法
:不僅鎖住掃瞄到的索引,而且還鎖住了這些索引覆蓋的範圍(gap
)
delete
或update
操作,這時讀取操作不會因此去等待行上鎖的釋放。相反地,innodb儲存引擎
會去讀取行的乙個快照資料。
快照資料是指行之前的版本的資料,該實現是通過不同事務隔離級別對快照資料的定義是不同的:undo
段來完成的。而undo
是用於事務中回滾資料的。因此快照資料本身沒有額外的開銷。此外,讀取快照資料是不需要上鎖的,因為沒有事務需要對歷史的資料進行修改。
read committed:非鎖定一致性讀,總是讀取被鎖定行的最新乙份快照資料。
repeatable read:非鎖定一致性讀,總是讀取事務開始時的行資料版本。
預設情況下,innodb
儲存引擎的select
操作使用一致性非鎖定讀。
但是在某些情況下,使用者需要顯示的對資料庫讀取操作進行加鎖以保證資料邏輯的一致性。這就要求資料庫支援加鎖語句。即使對於select
的唯讀操作,innodb儲存引擎
對於select
語句支援兩種一致性的鎖定讀:
① select … for update
② select … lock in share mode
select ... for update
: 會對讀取的行記錄加乙個x鎖
,其他事務不能對已鎖定的行加上任何鎖。
select ... lock in share mode
: 對讀取的行記錄加乙個s鎖
,其他事務可以向被鎖定的行加s鎖
,但是如果加x鎖
,則會被阻塞。
對於每個含有自增長的計數器的表進行插入操作時,這個計數器會被初始化,執行如下語句得到計數器的值:
select
max(auto_inc_col)
from t for
update
插入操作會依據這個自增長的計數器的值加1,然後賦值給自增長列。這種實現方式叫auto-inc locking
;(這是一種特殊的表鎖機制)
為了提高效能,鎖不是在事務完成後才釋放
,而是在完成對自增長值插入的sql語句後立即釋放
。
也就是說:事務沒釋放之前,只要插入操作執行完成,鎖就釋放掉了。
鎖的機制可以解決事務的隔離性
要求。
innodb儲存引擎鎖的演算法大致分類三種:
演算法名稱
描述解決的問題
record lock
單個行記錄
解決髒讀的
gap lock
間隙鎖,鎖定一定範圍,但是不包含記錄本身
解決幻象問題
next-key lock
上面兩個的結合;鎖定一定的範圍,並且鎖定記錄本身
解決幻象問題
講解:① record lock :總是會鎖住索引記錄;如果表中沒有設定任何乙個索引,那麼這時innodb
儲存引擎會使用隱式的主鍵進行鎖定。
② next-key lock鎖的目的是為了解決幻象問題
;(幻讀和不可重複讀)
對next-key lock
舉例說明:
假設索引中有10 、11、13、20
那麼該演算法會鎖定的區間:
(10,11], (11,13]
當插入新的記錄12時,則鎖定的範圍會變成:
(10, 11], (11, 12],(12,13]
說明:①record lock
總是去鎖定索引記錄。如果沒有建立索引,那麼就使用主鍵來進行鎖定。
②innodb
對行的查詢使用的就是next-key lock
演算法。
③ 當查詢的索引含有唯一屬性時,innodb儲存引擎會對next-key lock
降級為record lock
。即鎖住索引本身而不是範圍。
innodb儲存引擎不會根據每個記錄來產生行鎖,其是根據每個事務訪問的每個頁對鎖進行管理的,採用的是點陣圖的方式。因此不管乙個事務鎖住頁中的乙個記錄還是多個記錄,其開銷通常是一致的。在不同的事務下,當前事務可以讀到另外事務未提交的資料,簡單來說就是可以讀到髒資料。
乙個事務內多次讀取同一資料集合。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料集合,並做了一些dml
操作。導致第乙個事務兩次讀到的資料不一致。
不可重複讀和髒讀的區別:髒讀是讀到未提交的資料,而不可重複讀讀到的是已經提交的資料,但是其違反了資料庫事務一致性的要求。intention locks(意向鎖) 鎖基於表
record locks 鎖基於索引
gap locks 鎖基於索引
next-key locks 鎖基於索引
Mysql實戰學習筆記四 鎖
全域性鎖 全域性鎖就是對整個資料庫例項進行加鎖。命令為flush tables with read lock。執行後整個庫處於唯讀狀態,資料增刪改語句,資料定義語句 建表,修改表結構 和更新類事務提交都會被阻塞。全域性鎖常用於myisam資料庫的備份,加上唯讀鎖之後備份。但是整個庫唯讀存在風險。使用...
MySQL學習筆記5 MySQL 鎖機制
鎖的分類 從資料操作的型別 讀 寫 分 從對資料操作的顆粒度 特點 偏向myisam儲存引擎,開銷小,加鎖快,無死鎖,鎖定粒度大,發生鎖衝突的概率最高,併發最低。create 特點 偏向innodb儲存引擎,開銷大,加鎖慢 會出現死鎖 鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。innodb與...
MySQL學習筆記之全域性鎖和表鎖(六)
根據加鎖範圍,mysq裡面的鎖可以分為 全域性鎖,表鎖,行鎖 1.全域性鎖 全域性鎖就是對整個資料庫加鎖,使用命令flush tables with read lock ftwrl 當使用這個命令之後,全域性就處於乙個加鎖的狀態,其他執行緒下的語句就會被阻塞。資料的增刪改 資料定義語句和更新事務的提...