功能描述
Atomic DDLMySQL 8.0支持原子数据定义语言(DDL)语句。此功能称为 Atomic DDL。
Atomic DDL 将
- 对数据字典的更新
- 对存储引擎的操作
- 与DDL操作关联的二进制日志写入操作
组合到单个原子事务中。有关更多信息,请参见 第13.1.1节”原子数据定义语句支持”。
即使服务器在操作过程中暂停,该操作也可以提交,并在数据字典,存储引擎和二进制日志中保留适用的更改,或者回滚。
当前仅
InnoDB
存储引擎支持原子DDL
功能学习
通过在MySQL 8.0中引入MySQL数据字典,得以实现Atomic DDL的功能。在早期的MySQL版本中,元数据存储在元数据文件,非事务表和存储引擎特定的字典中,这需要中间提交。MySQL数据字典提供的集中式事务性元数据存储消除了这一障碍,从而可以将DDL语句操作重组为原子性的。
本部分的以下主题下介绍了原子DDL功能:
版本对比
对于与表相关的DDL操作,InnoDB
将DDL日志写入mysql.innodb_ddl_log
数据字典表。启用 innodb_print_ddl_logs
配置选项会将DDL恢复日志打印到 stderr
。
原子DDL功能更改了某些语句的行为:
DROP VIEW
如果命名视图不存在,并且不进行任何更改,则失败并显示错误。以前,该语句返回一个错误,指示哪些视图不存在,但也删除了确实存在的视图。DROP TABLE
如果命名表不存在,并且不进行任何更改,则失败并显示错误。以前,该语句返回错误,指示哪些表不存在,但还会删除那些存在的表。DROP TABLE
如果所有命名表都使用DDL支持的原子存储引擎,则为完全原子。DROP DATABASE
如果所有表都使用原子DDL支持的存储引擎,则为原子。但是,最后一次从文件系统中删除数据库目录不是原子事务的一部分。如果由于文件系统错误或服务器暂停而导致数据库目录删除失败,DROP DATABASE
则不会回滚事务。- 使用受原子DDL支持的存储引擎的表上的中断DDL操作不再导致存储引擎,数据字典和二进制日志之间出现差异,也不会留下孤立文件。
- 不再部分执行帐户管理对帐单。帐户管理语句对所有命名用户都成功,也可以回滚,如果发生错误,则无效。
更改DROP TABLE
, DROP VIEW
和帐户管理报表行为具有跨版本复制配置的影响。
< 8.0.3
# 5.7.20 |
一条DROP
表的命令中test01
表不存在,报错;test001
表存在被删除。
>= 8.0.3
# 8.0.20 |
一条DROP
表的命令中test01
表不存在,报错;test001
表存在,没有被删除。
对比
drop table test01,test001;
DDL行为变化对比 test01
test001
<8.0.3 ERROR 1051 (42S02) 删除 >=8.0.3 ERROR 1051 (42S02) 未删除
探索DDL Log
参数设置
-
| Property | Value |
| —————————————————————————————— | —————————————————— |
| Command-Line Format |--innodb-print-ddl-logs[={OFF|ON}]
|
| System Variable |innodb_print_ddl_logs
|
| Scope | Global |
| Dynamic | Yes |
|SET_VAR
Hint Applies | No |
| Type | Boolean |
| Default Value |OFF
|
数据字典
Enabling this option causes MySQL to write DDL logs to stderr
. For more information, see Viewing DDL Logs.
InnoDB
将DDL日志写入mysql.innodb_ddl_log
表以支持DDL操作的重做和回滚。该mysql.innodb_ddl_log
表是一个隐藏的数据字典表,位于mysql.ibd
数据字典表空间中。与其他隐藏数据字典表一样,该mysql.innodb_ddl_log
表不能在MySQL的非调试版本中直接访问。(请参见 第14.1节“数据字典架构”。)mysql.innodb_ddl_log
表的结构 与此定义相对应:CREATE TABLE mysql.innodb_ddl_log (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
thread_id BIGINT UNSIGNED NOT NULL,
type INT UNSIGNED NOT NULL,
space_id INT UNSIGNED,
page_no INT UNSIGNED,
index_id BIGINT UNSIGNED,
table_id BIGINT UNSIGNED,
old_file_path VARCHAR(512) COLLATE UTF8_BIN,
new_file_path VARCHAR(512) COLLATE UTF8_BIN,
KEY(thread_id)
);id
:DDL日志记录的唯一标识符。thread_id
:每个DDL日志记录都分配了一个thread_id
,用于重播和删除属于特定DDL操作的DDL日志。涉及多个数据文件操作的DDL操作会生成多个DDL日志记录。type
:DDL操作类型。类型包括FREE
(删除索引树),DELETE
(删除文件),RENAME
(重命名文件)或DROP
(从mysql.innodb_dynamic_metadata
数据字典表中删除元 数据)。space_id
:表空间ID。page_no
:包含分配信息的页面;例如,索引树的根页面。index_id
:索引ID。table_id
:表格ID。old_file_path
:旧表空间文件路径。由创建或删除表空间文件的DDL操作使用;也用于重命名表空间的DDL操作。new_file_path
:新表空间文件路径。由重命名表空间文件的DDL操作使用。
该实施例表明能够
innodb_print_ddl_logs
以查看写入到DDL日志strderr
用于CREATE TABLE
操作。
调试版本
使用MySQL的调试版本查看数据字典表
数据字典表在默认情况下受保护,但可以通过使用调试支持(使用-DWITH_DEBUG=1
CMake选项)编译MySQL 并指定 +d,skip_dd_table_access_check
debug
选项和修饰符来访问。有关编译调试版本的信息,请参见 第29.5.1.1节“编译MySQL以进行调试”。
警告不建议直接修改或写入数据字典表,否则可能会使您的MySQL实例无法使用。
在使用调试支持编译MySQL之后,使用以下 SET
语句使数据字典表对mysql客户端会话可见:
mysql> SET SESSION debug='+d,skip_dd_table_access_check'; |
使用此查询检索数据字典表的列表:
mysql> SELECT name, schema_id, hidden, type FROM mysql.tables where schema_id=1 AND hidden='System'; |
使用SHOW CREATE TABLE
查看数据字典表的定义。例如:
mysql> SHOW CREATE TABLE mysql.catalogs\G |
操作实践
mysql> set global innodb_print_ddl_logs=1; |
由于开启需要编译并加上debug参数,此处不做拓展。