1. 程式人生 > >mysql中InnoDB存儲引擎的行鎖和表鎖

mysql中InnoDB存儲引擎的行鎖和表鎖

nbsp 大於 依然 自帶 打折 一個 系統 指定 任務

Mysql的InnoDB存儲引擎支持事務,默認是行鎖。因為這個特性,所以數據庫支持高並發,但是如果InnoDB更新數據的時候不是行鎖,而是表鎖的話,那麽其並發性會大打折扣,而且也可能導致你的程序出錯。

而導致行鎖變為表鎖的情況之一就是:

  SQL的更新(update)或者刪除(delete)語句中未使用到索引,導致在InnoDB在對數據進行相應操作的時候必須把整個表鎖起來進行檢索(表鎖)。而如果使用了索引的話,InnoDB只會通過索引條件檢索數據,而只鎖住索引對應的行(行鎖)。

下面記錄一下我遇到的問題:

  描述:

  1. 系統中有一個實時的定時任務,當有條件觸發的時候,會更新對應的表,就先叫其為A表;
  2. 但是同時有一個任務有時候會對A表有寫操作,因此當進行測試的時候,有時候會不固定的出“Lock wait timeout exceeded”的錯誤。

  當出現這個問題的時候,從很多的地方進行了分析,然後都無法得到正確的解決方案(因為描述1模塊不是我寫的,所以沒有去查看更新表的代碼操作)

  導致原因:

    在描述1中定時任務更新表A的時候,更新條件中沒有使用索引,導致當進行定時任務更新表的時候形成了表鎖。然後因為表A數據量比較大,檢索較慢,然後導致了描述2中對表A的寫操作的等鎖超時。

最常見的索引:

  • 主鍵:眾所周知,自帶最高效的索引屬性
  • 唯一索引:屬性值重復率為0,可以作為業務主鍵
  • 普通索引:屬性值重復率大於0,不能作為唯一指定條件

  註意:對於普通索引,“重復率”低時,甚至接近主鍵或者唯一索引的效果時,依然是行鎖;但是如果“重復率”高時,Mysql不會把這個普通索引當做索引,即會造成一個沒有索引的SQL,從而形成表鎖。

mysql中InnoDB存儲引擎的行鎖和表鎖