鎖
概述
-
介紹
鎖是計算機協調多個行程或執行緒并發訪問某一資源的機制,在資料庫中,除傳統的計算資源(CPU、RAM、I/O)的爭用以外,資料也是一種供許多用戶共享的資源,如何保證資料并發訪問的一致性、有效性是所有資料庫必須解決的一個問題,鎖沖突也是影響資料庫并發訪問性能的一個重要因素,從這個角度來說,鎖對資料庫而言顯得尤其重要,也更加復雜,
-
分類
MySQL中的鎖,按照鎖的粒度分,分為以下三類:
- 全域鎖:鎖定資料庫中的所有表,
- 表級鎖:每次操作鎖住整張表,
- 行級鎖:每次操作鎖住對應的行資料,
全域鎖
-
介紹
全域鎖就是對整個資料庫實體加鎖,加鎖后整個實體就處于只讀狀態,后續的DML的寫陳述句,DDL陳述句,以及更新操作的事務提交陳述句都將被阻塞,
其典型的使用場景是做全庫的邏輯備份,對所有的表進行鎖定,從而獲取一致性視圖,保證資料的完整性,
-
演示


-
語法
加鎖:
flush tables with read lock;備份:
mysqldump -u用戶名 -p密碼 資料庫名稱 > 備份檔案的路徑,注意mysqldump是MySQL提供的一個工具,不是SQL陳述句,所以不要在MySQL的命令列運行,直接在系統的命令列運行,釋放鎖:
unlock tables; -
特點
資料庫中加全域鎖,是一個比較重的操作,存在以下問題:
- 如果在主庫上備份 ,那么在備份期間都不能執行更新,業務基本上就得停擺,
- 如果在從庫上備份,那么在備份期間從庫不能執行主庫同步過來的二進制檔案(binlog),會導致主從延遲,
在InnoDB引擎中,我們可以在備份時加上引數 --single-transaction 引數來完成不加鎖的一致性資料備份,
mysqldump --single-transaction -uxxx -pxxx 資料庫名 > 備份檔案路徑
表級鎖
-
介紹
表級鎖,每次操作鎖住整張表,鎖定粒度大,發生鎖沖突的概率最高,并發度最低,應用在MyISAM、InnoDB、BDB等存盤引擎中,
對于表級鎖,主要分為以下三類:
- 表鎖
- 元資料鎖(meta data lock,MDL)
- 意向鎖
-
表鎖
對于表鎖,分為兩類:
- 表共享讀鎖(read lock)
- 表獨占寫鎖(write lock)
語法:
- 加鎖:
lock tables 表名... read/write - 釋放鎖:
unlock tables / 客戶端斷開連接
讀鎖不會阻塞其他客戶端的讀,但是會阻塞寫,寫鎖即會阻塞其他客戶端的讀,又會阻塞其他客戶端的寫,


-
元資料鎖(meta data lock,MDL)
MDL加鎖程序是系統自動控制,無需顯式使用,在訪問一張表的時候會自動加上,MDL鎖主要作用是維護表元資料的資料一致性(這里元資料可以理解為表結構),在表上有活動事務的時候,不可以對元資料進行寫入操作,為了避免DML與DDL沖突,保證讀寫的正確性,
在MySQL5.5中引入了MDL,當對一張表進行增刪改查的時候,加MDL讀鎖(共享);當對表結構進行變更操作的時候,加MDL寫鎖(排他),
對應SQL 元資料鎖型別 說明 lock tables xxx read/writeSHARED_READ_ONLY / SHARED_NO_READ_WRITE select、select...lock in share modeSHARED_READ 與SHARED_READ、SHARED_WRITE兼容,與EXCLUSIVE互斥 insert、update、delete、select ... for updateSHARED_WRITE 與SHARED_READ、SHARED_WRITE兼容,與EXCLUSIVE互斥 alter table ...EXCLUSIVE 與其他的MDL都互斥 查看元資料鎖:
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks; -
意向鎖
為了避免DML在執行時,加的行鎖與表鎖的沖突就,在InnoDB中引入了意向鎖,使得表鎖不用檢查每行資料是否加鎖,使用意向鎖來減少表鎖的檢查,
- 意向共享鎖(IS):由陳述句select ... lock in share mode 添加,與表鎖共享鎖(read)兼容,與表鎖排他鎖(write)互斥,
- 意向排他鎖(IX):由insert、update、delete、select ... for update 添加,與表鎖共享鎖(read)及排他鎖(write)都互斥,意向鎖之間不會互斥,
可以通過以下SQL陳述句,查看意向鎖及行鎖的加鎖情況:
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;彈幕筆記摘要:
- 明顯寫鎖和誰都沖突,讀鎖和任何讀鎖都兼容,很好理解因為都只讀;
- 總的來說,意向鎖并不是真正意義上的鎖,只是一個記載鎖的資料結構,可以這么理解,不要被它的名字騙了;
- 要說意向鎖是鎖的話,那么它算是表級鎖;
- 鎖是一種資源,是要被爭搶的,被事務獲取;
- 產生意向鎖時也會產生元資料鎖;
- 原來懵的不止我一個(-_-);
- 意向鎖解決的是行鎖和表鎖的沖突問題;
行級鎖
-
介紹
行級鎖,每次操作鎖住對應的行資料,鎖定粒度最小,發生沖突的概率最低,并發度最高,應用在InnoDB存盤引擎中,
InnoDB的資料是基于索引組織的,行鎖是通過對索引上的索引項來實作的,而不是對記錄加的鎖,對于行級鎖,主要分為以下三類:
- 行鎖(Record Lock):鎖定單個記錄的鎖,防止其他事務對此進行update和delete,在RC、RR隔離級別下都支持,
- 間隙鎖(Gap Lock):鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事務在這個間隙進行insert,產生幻讀,
- 臨鍵鎖(Next-Key Lock):行鎖和間隙鎖組合,同時鎖住資料,并鎖住資料前面的間隙Gap,在RR隔離級別下支持,

-
行鎖
InnoDB實作了以下兩種型別的行鎖:
- 共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖;
- 排他鎖(X):允許獲取排他鎖的事務更新資料,阻止其他事務獲得相同資料集的共享鎖和排他鎖;

SQL 行鎖型別 說明 INSERT ... 排他鎖 自動加鎖 UPDATE ... 排他鎖 自動加鎖 DELETE ... 排他鎖 自動加鎖 SELECT(正常) 不加任何鎖 SELECT ... LOCK IN SHARE MODE 共享鎖 需要手動在SELECT之后加LOCK IN SHARE MODE SELECT ... FOR UPDATE 排他鎖 需要手動在SELECT之后加 FOR UPDATE -
默認情況下,InnoDB在REPEATABLE READ事務隔離級別運行,InnoDB使用next-key鎖進行搜索和索引掃描,以防止幻讀,
- 針對唯一索引進行檢索時,對已存在的記錄進行等值匹配時,將會自動優化為行鎖,
- InnoDB的行鎖是針對于索引加的鎖,不通過索引條件檢索資料,那么InnoDB將對表中的所有記錄加鎖,
-
可以通過以下SQL,查看意向鎖及行鎖的加鎖情況:
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks; -
彈幕摘要:記住這里,select一定要自己主動去加鎖,如果不主動加鎖是可以發生幻讀的;
-
間隙鎖/臨鍵鎖
默認情況下,InnoDB在REPEATABLE READ事務隔離級別運行,InnoDB使用next-key鎖進行搜索和索引掃描,以防止幻讀,
- 索引上的等值查詢(唯一索引),給不存在的記錄加鎖時,優化為間隙鎖,
- 索引上的等值查詢(普通索引),向右遍歷時最后一個值不滿足查詢需求時,next-key lock 退化為間隙鎖,
- 索引上的范圍查詢(唯一索引),會訪問到不滿足條件的第一個值為止,
注意 :間隙鎖的唯一目的就是防止其他事務插入間隙,間隙鎖可以共存,一個事務采用的間隙鎖不會阻止另一個事務在同一個間隙上采用間隙鎖,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/554299.html
標籤:其他
上一篇:Django遷移資料庫編碼錯誤
下一篇:返回列表
