MySQL 四 鎖

ellen艾琳發表於2020-11-02

四、MySQL 鎖
1、 鎖用於資料庫併發控制
2、    死鎖案例:
        1)將投資的錢拆封幾份借給借款人,這時處理業務邏輯就要把若干個借款人一起鎖住 select * from xxx where id in (xx,xx,xx) for update。
        2)批量入庫,存在則更新,不存在則插入。解決方法 insert into tab(xx,xx) on duplicate key update xx='xx'。
3、 對待死鎖常見的兩種策略:
    1)通過 innodblockwait_timeout 來設定超時時間,一直等待直到超時;
        InnoDB 預設是使用設定死鎖時間來讓死鎖超時的策略,預設 innodblockwait_timeout 設定的時長是 50s。
    2)發起死鎖檢測,發現死鎖之後,主動回滾死鎖中的某一個事務,讓其它事務繼續執行。
        設定 innodbdeadlockdetect 設定為 on 可以主動檢測死鎖,在 Innodb 中這個值預設就是 on 開啟的狀態。
4、 檢視死鎖
    使用命令 show engine innodb status 檢視最近的一次死鎖。
    InnoDB Lock Monitor 開啟鎖監控,每 15s 輸出一次日誌。使用完畢後建議關閉,否則會影響資料庫效能。
5、 MySQL 提供了全域性鎖、表級鎖、行級鎖。
6、 InnoDB 支援表級鎖和行級鎖,MyISAM 只支援表級鎖
7、 全域性鎖:對整個資料庫例項加鎖,它的典型使用場景就是做全庫邏輯備份。 
    這個命令可以使整個庫處於只讀狀態。使用該命令之後,資料更新語句、資料定義語句、更新類事務的提交語句等操作都會被阻塞。
8、 全域性鎖會導致的問題
    1)如果在主庫備份,在備份期間不能更新,業務停擺,所以更新業務會處於等待狀態
    2)如果在從庫備份,在備份期間不能執行主庫同步的 binlog,導致主從延遲
9、 如果使用全域性鎖進行邏輯備份就會讓整個庫成為只讀狀態,幸好官方推出了一個邏輯備份工具 MySQLdump 來解決了這個問題,只需要在使用 MySQLdump 時,
    使用引數 -single-transaction 就會在匯入資料之前啟動一個事務來保證資料的一致性,並且這個過程是支援資料更新操作的。
10、設定資料庫為全域性只讀鎖的兩種方法:
    1)使用命令 flush tables with read lock(簡稱 FTWRL)就可以實現設定資料庫為全域性只讀鎖
    2)set global readonly=true 設定資料庫為只讀
11、兩種方法的區別:FTWRL 和 set global readonly=true 都是設定整個資料庫為只讀狀態,但他們最大的區別就是,當執行 FTWRL 的客戶端斷開之後,整個資料庫會取消只讀,
    而 set global readonly=true 會一直讓資料處於只讀狀態。    
12、MySQL 裡標記鎖有兩種:表級鎖、後設資料鎖(meta data lock)簡稱 MDL。MDL不需要顯式使用,在訪問一個表的時候會被自動加上。
    表級鎖的語法是 lock tables t read/write。可以用 unlock tables 主動釋放鎖,也可以在客戶端斷開的時候自動釋放。
13、在對一個表做增刪改查操作的時候,加 MDL 讀鎖;當要對錶做結構變更操作的時候,加 MDL 寫鎖
14、MDL 會直到事務提交才會釋放,在做表結構變更的時候,一定要小心不要導致鎖住線上查詢和更新
15、InnoDB行鎖到底鎖了什麼?
    InnoDB的行鎖是通過給索引上的索引項加鎖來實現的。只有通過索引條件進行資料檢索,InnoDB才使用行級鎖,否則InnoDB將使用表鎖,鎖住索引的所有記錄
16、表鎖與行鎖的區別:
    鎖定粒度:表鎖 > 行鎖
    加鎖效率:表鎖 > 行鎖
    衝突概率:表鎖 > 行鎖
    併發效能:表鎖 < 行鎖    
17、行鎖的演算法:
    記錄鎖 Record Locks        單個行記錄上的鎖。鎖住具體的索引項
    間隙鎖 Gap Locks        鎖定一個範圍,不包括記錄本身。鎖住索引不存在的區間(左開右開)。只在RR事務隔離級別存在
    臨鍵鎖 Next-key Locks    鎖定一個範圍,包括記錄本身。鎖住索引的記錄+區間(左開右閉)。是 InnoDB預設的行鎖演算法
18、間隙鎖是專門用於解決幻讀問題的鎖,它鎖的了行與行之間的間隙,能夠阻塞新插入的操作。 間隙鎖的引入也帶來了一些新的問題,比如:降低併發度,可能導致死鎖。
19、自增鎖 AUTO-INC Locks:針對自增列自增長的一個特殊的表級別鎖。預設取值1,代表連續,事務未提交ID永久丟失
    show variables like 'innodb_autoinc_lock_mode';
20、共享鎖:又稱讀鎖 (read lock)。行鎖。是讀取操作建立的鎖。其他使用者可以併發讀取資料,但任何事務都不能對資料進行修改(獲取資料上的排他鎖),直到已釋放所有的共享鎖。
    如果事務對讀鎖進行修改操作,很可能會造成死鎖。
    解決不可重複度問題
    加鎖釋鎖方式:select * from users WHERE id=1 LOCK IN SHARE MODE;    commit/rollback
21、排它鎖 exclusive lock:又稱寫鎖(writer lock)。行鎖。悲觀鎖。會阻塞所有的排它鎖和共享鎖。
    解決賍讀問題
    加鎖釋鎖方式:
        delete / update / insert 預設加上X鎖
        SELECT * FROM table_name WHERE ... FOR UPDATE
        commit/rollback
22、悲觀鎖是由資料庫自己實現了的,要用的時候,我們直接呼叫資料庫的相關語句就可以了
23、共享鎖和排它鎖是悲觀鎖的不同的實現,它倆都屬於悲觀鎖的範疇
24、樂觀鎖是用資料版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現方式

相關文章