詳解MySQL8 0原子DDL語法

2022-09-21 23:39:12 字數 4655 閱讀 9257

原子ddl語句將資料字典更新、儲存引擎操作和與ddl操作相關聯的二進位制日誌寫入合併到單個原子操作中。該操作要麼提交,對資料字典、儲存引擎和二進位制日誌保留適用的更改,要麼回滾。

在mysql8.0中,原子ddl操作這一特性,支援表相關操作,例如create table、drop table等,也支援非表相關操作,例如create routine、drop trigger等。

其中:    支援的表操作包含:

drop、create、alter(操作物件是databases, tablespaces, tables, and in程式設計客棧dexes)語法、truncate語法

支援的非表操作包含:

create、drop、alter(操作物件是trigger、event、views、)

帳戶管理語句:使用者和角色的create、alter、drop和rename語句,以及grant和revoke語句

需要注意的是:跟表相關的ddl操作,需要保證儲存引擎是innodb的,非表相關的操作,則沒有要求。

有些sql語句不支援原子ddl,例如:

1、非innodb儲存引擎的表操作

2、install plugin和uninstall plugin操作(安裝外掛程式)

3、 install component和uninstallcomponent語句

4、create server、alter server和drop server語句(該語句是federated儲存引擎使用的,可暫時忽略)

原子操作的執行行為變化,跟資料字典的組織結構變化有關,在mysql8.0 之前,data dictionary除了存在與.frm, .trg, .opt 檔案外,還存在於系統表中(myisam 非事務引擎表中),在mysql8.0 ,data dictionary 全部存在於data dictionary storage engine(即 innodb表中),這使crash recovery 維持原子性成為了可能。下面的圖描述了資料字典的結構變化。

在mysql8.0之前,資料字典結構如下:

mysql8.0之後,資料字典變為:

下面來看2個具體的語法變化:

(1) drop語法的變化:

我們給資料庫裡面同時建立test1的表,並沒有test2的表,然後執行drop table test1,test2;觀察結果。

mysql5.7表現:

mysql> create table test1(id int);

query ok, 0 rows affected (0.01 sec)

mysql> show tables;

+----------------+

| tables_in_yeyz |

+----------------+

| t1 |

| t2 |

| t3 |

| test1 |

+----------------+

4 rows in set (0.00 sec)

mysql> drop table test1,test2;

error 1051 (42s02): unknown table 'yeyz.test2'

mysql> show tables;

+----------------+

| tables_in_yeyz |

+----------------+

| t1 |

| t2 |

| t3 |

+----------------+

3 rows in set (0.00 sec)

mysql8.0的表現:

mysql> create table test1(id int);

query ok, 0 rows affected (0.17 sec)

mysql> show tables;

+----------------+

| tables_in_yeyz |

+----------------+

| test1 |

+----------------+

1 row in set (0.00 sec程式設計客棧)

mysql> drop table test1,test2;

error 1051 (42s02): unknown table 'yeyz.test2'

mysql> show tables;

+----------------+

| tables_in_yeyz |

+----------------+

| test1 |

+----------------+

1 row in set (0.00 sec)

可以看到,mysql8.0中,當沒有test2的時候,並沒有刪除test1這個表,它將整個語句完全回滾;而mysql5.7中,誤刪除了test1這個表,沒有將整個語句完全回滾。

基於這種處理機制的不同,因此,我們在使用mysql5.7版本和mysql8.0版本做主從複製的時候,如果使用了類似上面的語句,就會發生報錯。因為二者的執行行為已經不一樣了。要想解決這個問題,需要使用drop table if not exists語法,同樣的,針對drop database、drop trigger等一系列操作,處理方法類似。還有一點值得注意,如果乙個資料庫中的所有表都是innodb的,那麼drop database才是原子的,否則,drop database不是原子的。

(2) create table...select 語法:

從mysql 8.0.21開始,在支援原子ddl的儲存引擎上,當使用基於row的複製模式時,create table...select...,該語句作為乙個事務記錄在二進位制日誌中。之前的版本中,它被記錄為兩個事務,乙個用於create表,另乙個用於insert資料。兩個事務之間或插入資料時發生伺服器故障可能導致複製了一張空表。通過引入原子ddl支援,create table ...select語句現在對於基於行的複製是安全的,並且允許與基於gtid的複製一起使用。

為了支援ddl操作的redo和rollback,innodb將ddl日誌寫入mysql.innodb_ddl_log表中,這個表存在於資料字典表空間中,如果使用者想要看這個表裡面的內容,需要開啟引數:

mysql> show variables like '%innodb_print_ddl_logs%';

+-----------------------+-------+

| variable_name | value |

+-----------------------+-------+

| innodb_print_ddl_logs | off |

+-----------------------+-------+

1 row in set (0.01 sec)

然後就可以在error log日誌中看到ddl操作的日誌了。相關日誌如下:

[note] [000000] innodb: ddl log insert : [ddl record: delete space, id=18, thread_id=7,

space_id=5, old_file_path=./test/t1.ibd]

[note] [000000] innodb: ddl log delete : by id 18

[note] [000000] innodb: ddl log insert : [ddl record: remove cache, id=19, thread_id=7,

table_id=1058, new_file_path=test/t1]

[note] [00000swhehahlu0] innodb: ddl log delete : by id 19

[note] [000000] innodb: ddl log insert : [ddl record: free, id=20, thread_id=7,

space_id=5, index_id=132, page_no=4]

[note] [000000] innodb: ddl log delete : by id 20

[note] [000000] innodb: ddl log post ddl : begin for thread id : 7

[note] [000000] innodb: ddl log post ddl : end for thread id : 7

mysql.innodb_ddl_log這個表的刷盤時機不受innodb_flush_logs_at_trx_commit引數的影響,這麼做的目的是為了避免資料檔案被ddl操作修改了,但是對應的redo log還沒有重新整理到磁碟,導致恢復或者回滾的時候報錯。

最後,我們介紹下整個原子ddl操作的幾個階段:

1、準備階段:建立需要的物件,寫入ddl log到mysql.innodb_ddl_log表,ddl log定義了如何前滾和回滾ddl操作

2、執行階段:執行ddl的操作流程

3、提交階段:更新資料字典,並提交資料字典事務

4、post-ddl階段:從mysql.innodb_ddl_log表重放並刪除ddl日誌。為了確保可以安全地執行回滾而不會引起不一致,在此最後階段執行磁碟上的檔案操作,例如重新命名或刪除資料檔案。此階段還將從mysql.innodb_dynamic_metadata資料字典表中刪除動態元資料,以用於drop table,truncate table和其他重建表的ddl操作。

mysql8 0提示命令 MySQL8 0操作命令

mysql8.0版本和mysql5.0的加密規則不一樣,而現在的很多任務具等都是不支援的,我們這裡使用的是將mysql使用者登入的加密規則修改為mysql native password的方法來進行解決的。修改加密規則alter user root localhost identified by p...

詳解MySQL8 0 常用命令

開啟遠端訪問 通過以下命令開啟root使用者遠端訪問許可權 create user root identified by password grant all on to root alter user root identified with mysql native password by pa...

mysql8 0修改登入

在mysql8.0當中的密碼認證外掛程式以經由mysql native password改為caching sha2 password 修改密碼的方式也發生了改變,控制台修改密碼方法如下 use mysql alter user root localhost identified by 新密碼 修改...