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
- mysql啟動和關閉外來鍵約束MySql
- 教你mysql如何增加外來鍵約束MySql
- MySQL禁用恢復外來鍵約束MySql
- Javaweb-約束-外來鍵約束JavaWeb
- Oracle定義約束 外來鍵約束Oracle
- mysql 刪除老是報外來鍵約束MySql
- mysql不能新增外來鍵約束怎麼辦MySql
- SQL的主鍵和外來鍵約束SQL
- oracle外來鍵約束的總結Oracle
- mysql資料庫匯入外來鍵約束問題MySql資料庫
- mysql~資料完整性考慮~外來鍵約束MySql
- SQL外來鍵約束的含義及建立SQL
- Oracle外來鍵約束中NULL的處理OracleNull
- mysql啟動和關閉外來鍵約束的方法(FOREIGN_KEY_CHECKS)MySql
- Mysql-基本練習(06-唯一約束、外來鍵約束、新增、刪除單列)MySql
- SQL SERVER中找出拙劣的約束,索引,外來鍵SQLServer索引
- 【實驗】【外來鍵】小議外來鍵約束對應用程式的影響
- AppBoxFuture(七): 分散式外來鍵約束APP分散式
- 詳解外來鍵約束(foreign key)
- 資料完整性約束:主鍵、外來鍵、各種約束的建立刪除語句
- 遷移後處理外來鍵約束的問題
- PostgreSQL11preview-支援陣列外來鍵約束SQLView陣列
- 外來鍵約束drop table cascade constraintsAI
- 【MySQL】MySQL進階(外來鍵約束、多表查詢、檢視、備份與恢復)MySql
- 查詢外來鍵約束、子表欄位等資訊的SQLSQL
- 修改外來鍵為validate時需要驗證資料是否符合外來鍵約束
- mysql中外來鍵約束級聯更新與刪除MySql
- 生成指令碼,得到所有表的外來鍵約束,然後刪除並重建這些約束指令碼
- 資料庫約束 主鍵-唯一性-Check-外來鍵資料庫
- 查詢(看)表的主鍵、外來鍵、唯一性約束和索引索引
- 關於外來鍵約束和對應主鍵資訊的查詢指令碼指令碼
- MYSQL的外來鍵MySql
- 分散式資料庫環境中,外來鍵約束的問題??分散式資料庫
- ORACLE: 查詢(看)表的主鍵、外來鍵、唯一性約束和索引Oracle索引
- 解決無法刪除表,提示被外來鍵約束引用
- 聊聊Oracle外來鍵約束(Foreign Key)的幾個操作選項Oracle
- oracle主外來鍵鎖_lock_約束Oracle