MySQL Lock wait timeout exceeded 錯誤解決(2026)|Transaction 鎖定 + deadlock + InnoDB 優化

MySQL Lock wait timeout exceeded 完整解決教學|InnoDB 鎖等待超時排查與修復(2026)
錯誤訊息:
Lock wait timeout exceeded; try restarting transaction

MySQL Lock wait timeout exceeded 是 InnoDB 常見的鎖等待超時錯誤。 當某個 transaction 正在等待資料鎖,但超過 MySQL 設定時間仍無法取得鎖時,就會被強制中斷。

這類問題常見於高併發系統,例如電商訂單、API 更新、後台批次處理等。 本質是「資料鎖競爭」,而不是單純 SQL 錯誤。

一、發生原因

  • Transaction 未 commit 或 rollback
  • 大量 UPDATE / DELETE 同時執行
  • 多請求同時修改同一筆資料
  • SQL 未使用 Index 導致鎖範圍過大
  • 長時間查詢佔用鎖資源
👉 InnoDB 是 row-level lock,但仍可能因範圍掃描變成大鎖

二、快速檢查問題來源

SHOW PROCESSLIST;
SHOW ENGINE INNODB STATUS;
SELECT * FROM information_schema.innodb_trx;
✔ 用來找出卡住的 transaction 與鎖來源

三、快速修復(暫時解法)

SET GLOBAL innodb_lock_wait_timeout = 120;
⚠️ 這只是延長等待時間,不能解決根本問題
⚠️ 更正:不需要重啟 MySQL。原文誤導了這一點——innodb_lock_wait_timeout 是 MySQL 的動態變數,用 SET GLOBAL 修改會立即生效,套用到之後新建立的連線(但不影響已經在等待中的現有連線)。重啟 MySQL 並非必要步驟,正式環境請不要只為了這個設定去重啟服務,徒增不必要的停機風險。只有在你想把這個設定寫進 my.cnf(或 my.ini),讓它在未來系統重啟後依然保留時,才需要重啟套用設定檔,但那是另一件事,跟現在用 SET GLOBAL 生效與否無關。

(選用)寫入設定檔讓變更永久保留

如果你確定要把這個 timeout 值長期固定下來,可以把它加進 my.cnf:

[mysqld]
innodb_lock_wait_timeout = 120

這個設定檔的變更只會在下一次系統重啟時才會被讀取套用;如果你現在就想讓新連線生效,前面的 SET GLOBAL 指令已經做到了,不需要額外重啟。

四、根本解法(最重要)

  • 確保 transaction 正確 commit / rollback
  • 避免長時間 transaction
  • 加 Index 減少掃描範圍
  • 拆分大量 UPDATE / DELETE
  • 避免多請求同時寫同一資料
✔ 核心重點:縮短鎖持有時間,而不是只提高 timeout

五、SQL 錯誤 vs 正確寫法

-- ❌ 錯誤:鎖整張表
UPDATE orders SET status = 1;
-- ✔ 正確:縮小鎖範圍
UPDATE orders SET status = 1 WHERE id = 100;
👉 沒有 WHERE + 沒有 Index = 高機率鎖爆

延伸閱讀(MySQL 錯誤排除系列・2026)

FAQ 常見問題

MySQL Lock wait timeout exceeded 是什麼?
代表 transaction 等待資料鎖超時,被 MySQL 強制中斷,通常是鎖競爭或未釋放 transaction。
這跟 deadlock 有什麼不同?
deadlock 是互相卡住形成循環等待,timeout 是等待太久被系統強制結束。
調整 timeout 可以解決嗎?
只能暫時緩解問題,無法解決鎖競爭的根本原因。
最常見原因是什麼?
未正確 commit transaction 或大量 UPDATE 同時執行。
如何找出卡住的 SQL?
使用 SHOW ENGINE INNODB STATUS 可以查看鎖與等待資訊。
Index 有幫助嗎?
有,可以減少掃描範圍,降低鎖定資料量。
CodeIgniter 會造成嗎?
如果 transaction 沒有正確關閉,也可能導致鎖累積。
會影響網站嗎?
會,可能導致 API 無回應或訂單失敗。
最佳解法是什麼?
正確設計 transaction + index 優化 + 縮短鎖時間,而不是只調 timeout。
修改 innodb_lock_wait_timeout 一定要重啟 MySQL 嗎?
不一定。用 SET GLOBAL 指令修改是動態變數,立即生效、不需要重啟,只對之後新建立的連線有效;只有想寫進 my.cnf 讓設定在未來重啟後仍保留時,才需要重啟套用設定檔,但那不影響當下已經透過 SET GLOBAL 生效的設定。

這是 MySQL 錯誤排除系列文章之一,包含記憶體、連線、鎖定三大類問題。