鎖是實現資料庫併發控制的重要手段,可以保證資料庫在多人同時操作時能夠正常執行。mysql 提供了全域性鎖、行級鎖、表級鎖。其中 innodb 支援表級鎖和行級鎖,myisam 只支援表級鎖。
是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的過程稱為死鎖。
死鎖是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的過程稱為死鎖。
將投資的錢拆封幾份借給借款人,這時處理業務邏輯就要把若干個借款人一起鎖住 select * from *** where id in (xx,xx,xx) for update。
批量入庫,存在則更新,不存在則插入。解決方法 insert into tab(xx,xx) on duplicate key update xx=『xx』。
對待死鎖常見的兩種策略:
innodb 預設是使用設定死鎖時間來讓死鎖超時的策略,預設 innodblockwait_timeout 設定的時長是 50s。
設定 innodbdeadlockdetect 設定為 on 可以主動檢測死鎖,在 innodb 中這個值預設就是 on 開啟的狀態。
全域性鎖就是對整個資料庫例項加鎖,它的典型使用場景就是做全庫邏輯備份。 這個命令可以使整個庫處於唯讀狀態。使用該命令之後,資料更新語句、資料定義語句、更新類事務的提交語句等操作都會被阻塞。
如果在主庫備份,在備份期間不能更新,業務停擺,所以更新業務會處於等待狀態。
如果在從庫備份,在備份期間不能執行主庫同步的 binlog,導致主從延遲。
如何處理邏輯備份時,整個資料庫不能插入的情況?
如果使用全域性鎖進行邏輯備份就會讓整個庫成為唯讀狀態,幸好官方推出了乙個邏輯備份工具 mysqldump 來解決了這個問題,只需要在使用 mysqldump 時,使用引數 -single-transaction 就會在匯入資料之前啟動乙個事務來保證資料的一致性,並且這個過程是支援資料更新操作的。
共享鎖又稱讀鎖 (read lock),是讀取操作建立的鎖。其他使用者可以併發讀取資料,但任何事務都不能對資料進行修改(獲取資料上的排他鎖),直到已釋放所有共享鎖。當如果事務對讀鎖進行修改操作,很可能會造成死鎖。
排他鎖 exclusive lock(也叫 writer lock)又稱寫鎖。
若某個事物對某一行加上了排他鎖,只能這個事務對其進行讀寫,在此事務結束之前,其他事務不能對其進行加任何鎖,其他程序可以讀取,不能進行寫操作,需等待其釋放。
排它鎖是悲觀鎖的一種實現,在上面悲觀鎖也介紹過。
若事務 1 對資料物件 a 加上 x 鎖,事務 1 可以讀 a 也可以修改 a,其他事務不能再對 a 加任何鎖,直到事物 1 釋放 a 上的鎖。這保證了其他事務在事物 1 釋放 a 上的鎖之前不能再讀取和修改 a。排它鎖會阻塞所有的排它鎖和共享鎖。
使用命令
flush tables with read lock(簡稱 ftwrl)就可以實現設定資料庫為全域性唯讀鎖。
除了使用 ftwrl 外,還可以使用命令 set global readonly=true 設定資料庫為唯讀。
ftwrl 和 set global readonly=true 有什麼區別?
ftwrl 和 set global readonly=true 都是設定整個資料庫為唯讀狀態,但他們最大的區別就是,當執行 ftwrl 的客戶端斷開之後,整個資料庫會取消唯讀,而 set global readonly=true 會一直讓資料處於唯讀狀態。
mysql 裡標記鎖有兩種:表級鎖、元資料鎖(meta data lock)簡稱 mdl。表鎖的語法是 lock tables t read/write。
可以用 unlock tables 主動釋放鎖,也可以在客戶端斷開的時候自動釋放。lock tables 語法除了會限制別的執行緒的讀寫外,也限定了本執行緒接下來的操作物件。
對於 innodb 這種支援行鎖的引擎,一般不使用 lock tables 命令來控制併發,畢竟鎖住整個表的影響面還是太大。
mdl:不需要顯式使用,在訪問乙個表的時候會被自動加上。
mdl 的作用:保證讀寫的正確性。
在對乙個表做增刪改查操作的時候,加 mdl 讀鎖;當要對錶做結構變更操作的時候,加 mdl 寫鎖。
讀鎖之間不互斥,讀寫鎖之間,寫鎖之間是互斥的,用來保證變更表結構操作的安全性。
mdl 會直到事務提交才會釋放,在做表結構變更的時候,一定要小心不要導致鎖住線上查詢和更新。
顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會 block 直到它拿到鎖。正因為如此,悲觀鎖需要耗費較多的時間,另外與樂觀鎖相對應的,悲觀鎖是由資料庫自己實現了的,要用的時候,我們直接呼叫資料庫的相關語句就可以了。
說到這裡,由悲觀鎖涉及到的另外兩個鎖概念就出來了,它們就是共享鎖與排它鎖。共享鎖和排它鎖是悲觀鎖的不同的實現,它倆都屬於悲觀鎖的範疇。
樂觀鎖是用資料版本(version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加乙個版本標識,一般是通過為資料庫表增加乙個數字型別的 version 欄位來實現。當讀取資料時,將 version 欄位的值一同讀出,資料每更新一次,對此 version 值加 1。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的 version 值相等,則予以更新,否則認為是過期資料。
因為沒有加鎖所以樂觀鎖的優點就是執行效能高。它的缺點就是有可能產生 aba 的問題,aba 問題指的是有乙個變數 v 初次讀取的時候是 a 值,並且在準備賦值的時候檢查到它仍然是 a 值,會誤以為沒有被修改會正常的執行修改操作,實際上這段時間它的值可能被改了其他值,之後又改回為 a 值,這個問題被稱為 aba 問題。
行級鎖是 mysql 中粒度最小的一種鎖,他能大大減少資料庫操作的衝突。
innodb 的行級鎖有共享鎖(s lock)和排他鎖(x lock)兩種。共享鎖允許事物讀一行記錄,不允許任何執行緒對該行記錄進行修改。排他鎖允許當前事物刪除或更新一行記錄,其他執行緒不能操作該記錄。
共享鎖:select … lock in share mode,mysql 會對查詢結果集中每行都新增共享鎖,前提是當前執行緒沒有對該結果集中的任何行使用排他鎖,否則申請會阻塞。
排他鎖:select * from t where id=1 for update,其中 id 字段必須有索引,mysql 會對查詢結果集中每行都新增排他鎖,在事物操作中,任何對記錄的更新與刪除操作會自動加上排他鎖。前提是當前沒有執行緒對該結果集中的任何行使用排他鎖或共享鎖,否則申請會阻塞。
MySql面試題總結
mysql主要考察方向 基本sql的編寫能力 資料庫鎖和索引的原理 事務 1.資料庫的三正規化是什麼?第一正規化 表中的列只能含有原子性 每個屬性不可再分 的值。每一列都是單獨的屬性,不可再分,但是存在資料冗餘大,插入異常,刪除異常,修改異常的問題。冗餘大 對應的屬性都一樣,在表中一直在重複這個屬性...
MySQL常問鎖的面試題
鎖 lock 在多人處理同乙個資料的時候,保證每次只有乙個人可以操作。mysql提供了頁鎖 全域性鎖 行鎖 表鎖。其中innodb採用的是行鎖和表鎖,myisam只支援表鎖。是指二個或者二個以上的程序在執行時候,因為爭奪資源造成相互等待的現象,程序一直處於等待中,無法得到釋放,這種狀態就叫做死鎖,批...
面試題總結 五 mysql
關於二者的對比與總結 1.count運算上的區別 因為myisam快取有表meta data 行數等 因此在做count 時對於乙個結構很好 的查詢是不需要消耗多少資源的。而對於innodb來說,則沒有這種快取。2.是否支援事務和崩潰後的安全恢復 myisam 強調的是效能,每次查詢具有原子性,其執...