MySQL·捉蟲動態·DROPDATABASE外來鍵約束的GTIDBUG
背景
MySQL的DDL沒有被設計成事務操作,因此DDL操作是無法回滾的(像PgSQL把DDL也設計成事務操作,DDL就可以在執行成功後被回滾操作取消)。這就會導致如果某個DDL語句內部被拆分為多個原子的DDL呼叫,那麼這個DDL語句就不具備中途執行失敗後回滾整個DDL語句的能力,也就是說,即使語句邏輯內的某個原子DDL呼叫失敗了,也無法回滾已經完成的那些原子DDL呼叫。
問題描述
DROP DATABASE 就是一個例子,對於MySQL而言,DROP DATABASE 並非是一個原子DDL操作,因為它是一個個刪除DB下的每張表,而 DROP TABLE 操作本身是會做預檢查的,無法刪除就會取消刪表操作返回失敗,所以 DROP TABLE 才能認為是原子的DDL呼叫。 這就會引起一個問題,如果一個DB中的某張表DROP失敗了,實際上 DROP DATABASE 作為一個整體是執行失敗的,但是DB中已經有一些表被刪除了,因此Binlog中會記錄成多個 DROP TABLE 操作,而不是一個 DROP DATABASE 語句。 如果被刪除的表的表名都不長,還是會記錄成一個刪除多張表的 DROP TABLE 語句(DROP TABLE tbl1, tbl2, …),但是如果表名總長度太長,MySQL會拆分為多個 DROP TABLE 語句來記錄。 沒有GTID的時候這似乎也不是什麼大問題,但是引入GTID之後就有一個問題:每個語句只分配一個GTID。如果一個 DROP DATABASE 語句被拆分為多個 DROP TABLE 語句,Binlog中就會出現多個 DROP TABLE 事件共用一個GTID的情況!
舉個例子:
這裡因為 db2.t3 表引用了 db1.t1 的欄位作為外來鍵約束,所以當 db1 做 DROP DATABASE 刪除到 t1 表時就報錯了,但此時很多表已經被刪除了。我們看Binlog中記錄的內容:
3個 DROP TABLE 語句都是同一個GTID:340d95b8-a699-11e4-868d-a0d3c1f20ae4:61
這就導致備庫複製報錯:
解決方案
怎麼解決這個問題呢?
1. 讓MySQL支援DDL事務
2. 對DROP DATABASE操作進行預檢查
第一種方案對MySQL改動太大了,完全不現實。因此我們採用了第二種方案,也間接實現了 DROP DATABASE 這個操作的原子性。 DROP DATABASE 之所以出現上面的狀況,就是因為沒有先檢查表是否可以刪除,而是走一步看一步,一個個刪的時候才看能不能刪除。我們對MySQL做了修正,對於DB中的每張表,在 DROP DATABASE 執行之前,都先預檢查所有可能導致刪除表失敗的條件,如果一旦發現某張表會無法刪除,就放棄整個 DROP DATABASE 操作,提示使用者刪除錯誤,讓使用者先自行解決問題後,再重新執行 DROP DATABASE。
例如上面例子中的情況,本來 DROP DATABASE 執行到有外來鍵約束的表時會報錯:
但此時其他表已經刪除了,而我們修正以後,同樣的操作會報一個Error和一個Warning,並且沒有真的刪任何表:
這裡提示了使用者有表存在問題無法刪除,讓使用者先處理掉之後,再來執行 DROP DATABASE。此時庫下面所有的表都還在,一定要預檢查通過才會真的刪除。
相關文章
- 教你mysql如何增加外來鍵約束MySql
- 外來鍵約束
- Javaweb-約束-外來鍵約束JavaWeb
- mysql不能新增外來鍵約束怎麼辦MySql
- 關於外來鍵約束
- 約束外來鍵筆記筆記
- oracle外來鍵約束的總結Oracle
- mysql~資料完整性考慮~外來鍵約束MySql
- AppBoxFuture(七): 分散式外來鍵約束APP分散式
- SQL外來鍵約束的含義及建立SQL
- Mysql-基本練習(06-唯一約束、外來鍵約束、新增、刪除單列)MySql
- 【MySQL】MySQL進階(外來鍵約束、多表查詢、檢視、備份與恢復)MySql
- 生成指令碼,得到所有表的外來鍵約束,然後刪除並重建這些約束指令碼
- 聊聊Oracle外來鍵約束(Foreign Key)的幾個操作選項Oracle
- MYSQL的外來鍵MySql
- Mysql關於資料庫是否應該使用外來鍵約束詳解說明創磅MySql資料庫
- MySQL 約束MySql
- MariaDB資料庫的外來鍵約束例項程式碼介紹詳解資料庫
- 批量刪除MSSQL 中主外來鍵約束SQL
- 資料遷移無法新增外來鍵約束,錯誤程式碼 1215
- ConstraintLayout 之 ConstraintSet 動態修改約束(動畫)AI動畫
- Mysql入門【Mysql約束】MySql
- 主鍵約束、唯一約束和唯一索引索引
- MySQL自增約束MySql
- MySQL 欄位約束MySql
- [資料庫]資料庫中為什麼不推薦使用外來鍵約束資料庫
- Laravel 學習總結二:get () 和 first () 的區別、@each () 的用法和新增外來鍵約束Laravel
- mysql建立外來鍵語句MySql
- 《資料庫系統概論》5.0——常見約束 大學生學習筆記(主鍵 外來鍵)資料庫筆記
- mysql資料庫約束MySql資料庫
- MySQL——約束(constraint)詳解MySqlAI
- [20180423]關於閃回表與主外來鍵約束.txt
- 【SQL】15 SQL 約束(Constraints)、NOT NULL 約束、UNIQUE 約束、PRIMARY KEY 約束、FOREIGN KEY 約束、CHECK 約束、DEFAULT約束SQLAINull
- 5_MySQL 表的欄位約束MySql
- MySQL 中的約束及相關操作MySql
- MySQL之完整性約束MySql
- MySQL唯 一鍵約束場景下卻能插入重複行?MySql
- Masonry動畫更新約束動畫
- mysql新增約束語句筆記MySql筆記