Mysql

MySQL InnoDB 遷移自定義實現:如何處理在後台觸發送出的 DML 語句?

  • June 21, 2022

在對該主題進行了一些討論之後,我可以假設 MySQL InnoDB 有一個非常令人沮喪的事實:當涉及到 DML 時,它不支持(原子)事務。

如果您使用數據進行數據庫遷移,那麼有一個相當簡單的解決方案可以使其完全失敗或成功完成。

START TRANSACTION;

INSERT INTO orders(orderNumber,orderDate) VALUES (1,'2020-05-31');
INSERT INTO orders(orderNumber,orderDate) VALUES (1,'2020-05-31');

COMMIT;

事務是針對一個或多個數據庫中的數據的數據庫操作的原子單元。

不幸的是,以下情況並非如此:

START TRANSACTION;

CREATE TABLE Persons ( PersonID int, LastName varchar(255),FirstName varchar(255));
CREATE TABLE Ducks ( DuckID int, DuckName varchar(255));
CREATE INDEX duckname_index ON Ducks (DuckName varchar(255));

COMMIT;

每個語句都將創建一個隱式送出,因此如果在 MySQL 數據庫損壞和遷移一半之間遷移失敗。

從文件:

有些語句不能回滾。通常,這些包括數據定義語言 (DDL) 語句,例如創建或刪除數據庫的語句,創建、刪除或更改表或儲存常式的語句。您應該在設計事務時不包含此類語句。如果您在無法回滾的事務中早期發出語句,然後另一個語句稍後失敗,則在這種情況下無法通過發出 ROLLBACK 語句來回滾事務的全部效果。

由於我們必須為某個軟體實施自定義遷移系統,我們現在想知道如何解決這個問題?例如 Symfony ( https://symfony.com/ ) Doctrine ( https://www.doctrine-project.org/ ) 如何在內部解決這個問題?

想法:

  1. 如果出現錯誤,請在 CI/CD 級別解決並恢復舊數據庫?缺點:聽起來真的很笨拙。
  2. 僅允許僅包含一個 DML 語句的遷移,並嚴格分開 DML 和 DDL 遷移。缺點:每個生產部署將有 10 個或數百個遷移文件。

我仍然希望有更好的方法嗎?該問題的最佳實際解決方案是什麼 - 如果有的話?

我想你的意思是DDL。DML 語句就像 SELECT/INSERT/UPDATE/DELETE,我想不出導致隱式送出的 DML 語句之一。

如果您擔心此類遷移中途發生崩潰,請在其自己的遷移步驟中應用每個 DDL 語句。通常,遷移框架為每個遷移分配一個“版本”ID,因此它們知道哪些遷移尚未應用。因此,如果一系列遷移中斷,那麼只需重新執行遷移工具,它就會找出中斷的位置並執行後續遷移。

但老實說,大多數人並不介意。在將 DDL 語句送出到您的儲存庫之前,您應該仔細測試它們。所以語法錯誤或導致失敗的東西的可能性應該接近於零。

如果任何人在沒有通過遷移系統的情況下對該數據庫實例進行操作,則可能會發生邏輯故障(例如,無法添加表,因為該名稱的表已經存在)。沒有任何自動化系統可以解釋人類引入的所有可能的混亂。只要確保你的隊友能夠配合自動化。

中斷多語句遷移的崩潰很少見。在這些情況下,您可能需要進行一些手動修復才能執行後續遷移。這很不方便,但這不是世界末日。

最後,遷移的另一種方法是聲明性地描述表在系統的目前狀態下應該是什麼,並讓工具確定要應用哪些遷移。例如,這就是像Skeema這樣的工具的策略。

引用自:https://dba.stackexchange.com/questions/313608