全局鎖
對整個庫實例加鎖骏全。
讓整個庫處于只讀狀態(tài)的時候,可以使用這個命令尼斧,之后其他線程的以下語句會被阻塞:
增刪改姜贡、建表、修改表結(jié) 更新類事務(wù)的提交
MySQL 提供了一個加全局讀鎖的方法棺棵,命令是Flush tables with read lock
(FTWRL)楼咳。用 unlock tables
主動釋放鎖,也可以在客戶端斷開的時候自動釋放烛恤。
使用場景是母怜,做全庫邏輯備份, 把整庫每個表都 select 出來存成文本。
主庫上備份缚柏,業(yè)務(wù)基本上就得停擺苹熏;
從庫上備份,不能執(zhí)行主庫同步過來的 binlog币喧,會導致主從延遲
所以盡量不用, 而是利用事務(wù)的視圖, 除非 是MyISAM 這種不支持事務(wù)的引擎, 只要庫里面有表不支持事務(wù), 就不能用了
可重復讀 : 數(shù)據(jù)庫里在事務(wù)啟動時創(chuàng)建一個視圖,整個事務(wù)存在期間都用這個視圖轨域。
官方自帶的邏輯備份工具是 mysqldump。
mysqldump 使用參數(shù)–single-transaction ,導數(shù)據(jù)之前就會啟動一個事務(wù)粱锐,來確保拿到一致性視圖疙挺。這個過程中數(shù)據(jù)是可以正常更新的 (MVCC )
為什么不使用 set global readonly=true 的?
readonly 方式也可以讓全庫進入只讀狀態(tài)怜浅,但:
1.在有些系統(tǒng)中铐然,readonly 的值會被用來做其他邏輯,比如用來判斷一個庫是主庫還是備庫恶座。因此搀暑,修改 global 變量的方式影響面更大
2.在異常處理機制上有差異。如果執(zhí)行 FTWRL 命令之后由于客戶端發(fā)生異常斷開跨琳,那么 MySQL 會自動釋放這個全局鎖自点,整個庫回到可以正常更新的狀態(tài)。而將整個庫設(shè)置為 readonly 之后脉让,如果客戶端發(fā)生異常桂敛,則數(shù)據(jù)庫就會一直保持 readonly 狀態(tài)功炮,這樣會導致整個庫長時間處于不可寫狀態(tài),風險較高术唬。
表鎖
表語法是 lock tables … read/write薪伏。可以用 unlock tables 主動釋放鎖粗仓,也可以在客戶端斷開的時候自動釋放嫁怀。
在還沒有出現(xiàn)更細粒度的鎖的時候,表鎖是最常用的處理并發(fā)的方式借浊。InnoDB 支持行鎖塘淑,就不用了
innodb 在非索引上查詢的鎖 ,如果非要加鎖的話 是表級鎖 ....其實默認多版本并發(fā) 不加鎖
MDL(metadata lock)
MDL 不需要顯式使用,系統(tǒng)默認會加的,在訪問一個表的時候會被自動加上蚂斤。
作用是存捺,保證讀寫的正確性。
對一個表做增刪改查操作的時候曙蒸,加 MDL 讀鎖(讀鎖之間不互斥,可同時對一張表增刪改查)
對表做結(jié)構(gòu)變更操作的時候召噩,加 MDL 寫鎖。
讀寫鎖逸爵、寫鎖 之間是互斥的,來保證變更 表結(jié)構(gòu) 操作的安全性凹嘲。
坑:
session C alter改表結(jié)構(gòu), 得了寫鎖, 又要改表中數(shù)據(jù), 要等讀鎖, 而事務(wù)沒結(jié)束, 寫鎖不會放開,阻塞住了, 下面都不能進行了,如果某查詢語句頻繁师倔,客戶端有重試機制,超時后會再起一個新 session 再請求的話周蹭,這個庫的線程很快就會爆滿趋艘。
所以,最好是 在 alter table 語句里面設(shè)定等待時間,如果在這個指定的等待時間里面能夠拿到 MDL 寫鎖最好凶朗,拿不到也不要阻塞后面的業(yè)務(wù)語句瓷胧,先放棄。之后開發(fā)人員或者 DBA 再通過重試命令重復這個過程棚愤。
MariaDB 支持 DDL NOWAIT/WAIT n 這個語法搓萧。
ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...