mysql的鎖

MySQL的鎖mysql

  • 全局鎖:對數據庫實例加鎖
    • MySQL提供了一個加全局讀鎖的方法:Flush tables with read lock(FTWRL)
    • 使用場景:作全庫邏輯備份。
    • 官方自帶的邏輯備份工具mysqldump,使用時帶上參數-single-transaction,導數據以前就會啓動一個事務,來確保拿到一致性視圖。因爲MVCC的支持,這個過程是能夠正常更新的。
    • FTWRL用在MyISAM這種不支持事務的引擎上。
    • single-transaction方法只能用在全部的表都使用事務引擎的庫。
    • set global readonly=true也可讓全庫進入只讀狀態,可是不推薦用在全庫備份的場景下。
  • 表級鎖
    • 分類
      • 表鎖
        • 語法
          • 加鎖:lock tables ... read/write
          • 釋放鎖:unlock tables
        • 使用場景:非事務引擎
      • 元數據鎖(meta data lock,MDL)
        • MySQL5.5版本中引入了MDL,分爲MDL讀鎖和MDL寫鎖。
        • 不須要顯式使用,在訪問一個表的時候會被自動加上。
        • 事務中的MDL鎖,在語句開始時申請,可是在語句結束後不會立刻釋放,而是等整個事務提交後再釋放。對於長事務,事務不提交,就會一直佔着MDL鎖(重要)
        • 做用:保證讀寫的正確性。
        • 規則:
          • 讀鎖之間不互斥,能夠有多個線程同時對一張表(應該指的是表的元數據)增刪改查。
          • 讀寫鎖之間、寫鎖之間是互斥的,用來保證變動表結構操做的安全。若是兩個線程要同時給一個表加字段,其中一個要等另外一個執行完才能開始執行。
        • 避坑指南
          • 給一個小表加個字段致使整個庫掛了!!!如何安全地給小表加字段?
            • 2個知識點:
              • 給一個表加字段、或者修改字段、或者加索引,須要掃描全表的數據。
              • 事務中的MDL鎖,在語句開始時申請,可是在語句結束後不會立刻釋放,而是等整個事務提交後再釋放。
            • 解決方法
              • 解決長事務:事務不提交,就會一直佔着MDL鎖。
              • 查詢information——schema庫的innodb_trx表中正在執行的長事務,暫停長事務,而後再修改表。
              • 對與熱點表的修改,kill事務的方式很差用,能夠在alter table 語句裏設定等待時間。若是在指定的等待時間裏拿到了MDL鎖最好,拿不到也不會阻塞後面的業務語句,先放棄。以後開發人員或者DBA再重試命令。
              • MariaDB和AliSQL目前都支持DDL NOWAIT/WAIT n 這個語法
  • 行鎖
    • 定義:針對數據庫表中行記錄的鎖。
    • MySQL的行鎖是引擎層由各個引擎本身實現的。MyISAM引擎不支持行鎖。
    • 兩階段鎖協議:在InnoDB事務中,行鎖是在須要的時候才加上的,但並非不須要了就馬上釋放,而是等到事務結束才釋放。
    • 建議:若是事務中須要鎖多個行,要把最可能形成鎖衝突、最可能影響併發度的鎖儘可能日後放。
    • 死鎖和死鎖檢測
      • 解決死鎖的策略
        • 一:直接進入等待,直到超時,超時時間經過參數innodb_lock_wati_timeout來設置。InnoDB中,這個值默認是50s,這個值對於在線服務來講,是沒法接受的。把這個值設置成一個小的值也是不合理的。因此不推薦這個方式來解決死鎖。
        • 二:發起死鎖檢測,發現死鎖後,主動回滾死鎖鏈條中的某一個事務,讓其餘事務得以繼續執行。設置參數innodb_deadlock_detect=on。InnoDB中,這個值默認就是on,也就是說InnoDB會自動死鎖檢測。
          • 每一個新來的被堵住的線程,都要判斷會不會因爲本身的加入致使了死鎖。這是一個時間複雜度爲O(n)的操做。
          • 當有1000個線程要同時更新同一行,那麼死鎖檢測操做就是(1000*1000)百萬量級的。雖然最終檢測的結果是沒有死鎖,可是這期間消耗大量的CPU資源。
      • 如何解決由熱點行更新致使的性能問題呢?
        • 思路一:臨時把死鎖檢測關掉(前提是確保這個業務必定不會出現死鎖)
        • 思路二:控制併發度。
          • 客戶端作併發控制(當客戶端多的時候不太可行)
          • 在中間件中實現,或者修改MySQL源碼,對於向同行的更新,在進入引擎前排隊。這樣InnoDB內部就不會有大量的死鎖檢測工做了。
          • 從設計上作優化:將一行改爲邏輯上的多行來減小鎖衝突。(須要根據業務邏輯作詳細設計)
相關文章
相關標籤/搜索