MySQL InnoDB鎖機制詳解 為什麼我們需要鎖?先別急著回答、回想一下我們在逛淘寶下訂單時的一個場景: InnoDB 是行鎖、不存在鎖升級問題、也就是、鎖住 1 行和鎖住 1 千萬行的開銷是一樣 但是、InnoDB 行鎖仍然存在一般的鎖在高並發下所特有的"劣根性": ● 丟失更新:A的修改被B覆蓋、謂之"前浪總被後浪蓋" ● 髒讀:不同事務間、讀到未提交的數據 ● 不可重復讀:同一事務、兩次讀不同 外鍵無索引是Oracle 死鎖發生的常見原因、而在InnoDB 、我趕腳、 InnoDB 是"買一送一"、並且、不要你也得要、因為、 在 InnoDB裡、會自動對外鍵添加索引、人為刪除外鍵索引會報錯 有興趣的朋友、對子表 show index from tbname; 便會發現 InnoDB 鎖有 3種類型: ● Record Lock:鎖定單條記錄 ● Gap Lock:鎖定一個范圍的記錄、但不包括記錄本身 ● Next-Key Lock:鎖定一個范圍的記錄、並且包含記錄本身、這是默認的鎖類型 那麼、我們該如何顯示加 InnoDB 鎖呢?有 2種方式: ● select ... lock in share mode:加 S 鎖 ● select ... for update:加 X 鎖 InnoDB 鎖性能監控 [sql] view plaincopy mysql> show status like 'innodb_row_lock_%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | Innodb_row_lock_current_waits | 0 | | Innodb_row_lock_time | 23265 | | Innodb_row_lock_time_avg | 2115 | | Innodb_row_lock_time_max | 7401 | | Innodb_row_lock_waits | 11 | +-------------------------------+-------+ 5 rows in set (0.00 sec) 解釋如下: Innodb_row_lock_current_waits:當前等待鎖的數量 Innodb_row_lock_time:系統啟動到現在、鎖定的總時間長度 Innodb_row_lock_time_avg:每次平均鎖定的時間 Innodb_row_lock_time_max:最長一次鎖定時間 Innodb_row_lock_waits:系統啟動到現在、總共鎖定次數 影響 InnoDB 的幾個參數 [sql] view plaincopy mysql> select @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ --設定事務隔離級別 mysql> select @@global.autocommit; +---------------------+ | @@global.autocommit | +---------------------+ | 1 | +---------------------+ --自動提交 mysql> select @@global.innodb_table_locks; +-----------------------------+ | @@global.innodb_table_locks | +-----------------------------+ | 1 | +-----------------------------+ --InnoDB 內部鎖定一個表 mysql> select @@global.innodb_lock_wait_timeout; +-----------------------------------+ | @@global.innodb_lock_wait_timeout | +-----------------------------------+ | 50 | +-----------------------------------+ --控制等待時間 mysql> select @@global.innodb_locks_unsafe_for_binlog; +-----------------------------------------+ | @@global.innodb_locks_unsafe_for_binlog | +-----------------------------------------+ | 0 | +-----------------------------------------+ --insert into ...select 是否鎖定源表