為什麼 MySQL 禁止在儲存過程中使用 LOCK TABLES?
我已經閱讀了 MySQL 參考手冊的幾個部分,雖然它反复聲明
LOCK TABLES
不能在儲存過程中使用,但我從未找到其背後原因的解釋。
tl;博士
禁止它們是為了防止您無意中導致您可能不希望發生的送出(例如,通過在事務中間呼叫儲存過程)。
複製自(現已棄用)MySQL 郵件列表:
以下是 Shawn Green 對我在那裡發表的文章的回答,然後是他對同一執行緒中另一張海報的回复:
你好傑夫,
2018 年 8 月 13 日下午 12:05,jeff@stripped 寫道:
您好,我已經閱讀了參考手冊的幾頁,並且我看到了幾個實例,其中聲明在儲存過程中不允許使用 LOCK TABLES(和 UNLOCK TABLES),但到目前為止,我還沒有找到解釋為什麼會這樣。有人可以啟發我嗎?
謝謝
通常,列表比這更敏感。這是一個非常簡單的問題,在我需要介入作為後盾之前,通常有人會處理這些問題。
無法在儲存程序中執行 LOCK TABLE 命令的關鍵在於: https ://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html
LOCK TABLES 不是事務安全的,它會在嘗試鎖定表之前隱式送出任何活動事務。
儲存程序在啟動它們的事務範圍內執行。這確定了哪些行集對常式是“可見的”,並在需要時確定可以送出或回滾的內容的界限。
(一個簡單的例子)
* your session: START TRANSACTION * your session: ...other data activity ... * your session (INSERT ... ) * causes an INSERT trigger to fire * which calls a stored procedure
如果該儲存過程或該觸發器呼叫了 LOCK TABLE 命令,它將強制送出您在那之前一直在其中工作的現有事務。即使後面的步驟需要您發出 ROLLBACK 命令,您半完成的工作也會完全送出。
請注意,即使您不在多語句事務中,任何由使用者命令呼叫或在使用者命令範圍內執行的儲存程序都是該小型(自動送出)事務的一部分。
這有幫助嗎?
–
Shawn Green
MySQL 高級首席技術支持工程師
Oracle USA, Inc. - 硬體和軟體,旨在協同工作。
辦公室:田納西州布朗特維爾
你好,莫根斯,
2018 年 8 月 18 日下午 2:32,Mogens Melander 寫道:
伙計們,
我想我從很久以前就記得這件事。
你可以要求一個鎖,如果它是安全的,就可以了。
例如,如果在您的目標表上有待處理的事務,您會得到一個 NO。
但話又說回來。我可能是錯的,肖恩是這方面的權威。
您的鎖請求將一直等到所有現有的讀取器或寫入器(取決於您請求的鎖的類型)都使用完您想要鎖定的表。通過擴展,這意味著針對您想要鎖定的表的任何活動事務也需要在您的請求被批准之前送出或回滾。針對該表的任何新操作都將在您的 LOCK 請求之後排隊。這讓不止一個 DBA 感到困惑,因為他們沒有意識到 LOCK 將成為如此緊密的瓶頸。
這些類型的全表鎖存在於各個儲存引擎或事務控制程式碼的阻塞/鎖定協調之上。它們在我們程式碼的“伺服器層”中進行管理。
這種範圍分離是為什麼在同一數據管理過程中混合事務和非事務表通常不受歡迎的原因之一。要麼是全事務的(InnoDB),要麼不是。該行為將更容易預測,允許您的開發人員放心地使用事務控制命令 (BEGIN/COMMIT/ROLLBACK/…) 或 LOCK 命令。
您的,
–
Shawn Green
MySQL 高級首席技術支持工程師
Oracle USA, Inc. - 集成雲應用程序和平台服務
辦公室:田納西州 Blountville
我也找不到“這就是為什麼”的聲明,但從閱讀下面連結中的項目來看,它似乎是以下各項的組合:
- 首選最佳實踐:使用 SELECT…FOR UPDATE
- 行級鎖定優先於表級鎖定
- 與並發性和行級鎖定的更細粒度相關的性能
- MySQL 儲存過程論壇上出現的其他替代方案包括如果表級鎖定確實合理或使用事務而不是表級鎖定,則切換儲存引擎(儘管這仍然不會將 LOCK TABLES 語句轉換為 SP)。這些選舉可能歸結為原始問題中未出現的其他考慮因素。
- 還看到了關於儲存過程的聲明,聲明不允許使用“任意 SQL 語句”。我沒有尋找“任意 SQL”的列表。
祝你好運