MySQL8.0新特性——支持原子DDL语句

   MySQL 8.0开始支持原子数据定义语言(DDL)语句。此功能称为原子DDL。原子DDL语句将与DDL操做关联的数据字典更新,存储引擎操做和二进制日志写入组合到单个原子事务中。即便服务器在操做期间暂停,也会提交事务,并将适用的更改保留到数据字典,存储引擎和二进制日志,或者回滚事务。html

 

   经过在MySQL 8.0中引入MySQL数据字典,能够实现Atomic DDL。在早期的MySQL版本中,元数据存储在元数据文件,非事务性表和存储引擎特定的字典中,这须要中间提交。MySQL数据字典提供的集中式事务元数据存储消除了这一障碍,使得将DDL语句操做重组为原子事务成为可能。mysql

 

官方文档:sql

https://dev.mysql.com/doc/refman/8.0/en/atomic-ddl.html数据库

 

 

一、支持的DDL语句缓存

 原子DDL功能支持表和非表DDL语句。与表相关的DDL操做须要存储引擎支持,而非表DDL操做则不须要。目前,只有InnoDB存储引擎支持原子DDL。安全

 

①:受支持的表DDL语句包括 CREATE,ALTER和 DROP对数据库,表,表和索引,以及语句 TRUNCATE TABLE声明。服务器

②:支持的非表DDL语句包括:函数

   CREATE和DROP 语句,以及(若是适用)ALTER 存储程序,触发器,视图和用户定义函数(UDF)的语句。atom

   帐户管理语句: CREATE,ALTER, DROP,,若是适用, RENAME报表用户和角色,以及GRANT 和REVOKE报表。调试

 

1.一、原子DDL功能不支持如下语句:

①:涉及除存储引擎以外的存储引擎的与表相关的DDL语句InnoDB。

②:INSTALL PLUGIN和 UNINSTALL PLUGIN 陈述。

③:INSTALL COMPONENT和 UNINSTALL COMPONENT 陈述。

④:CREATE SERVER, ALTER SERVER和 DROP SERVER语句。

 

二、原子DDL特性:

①:元数据更新,二进制日志写入和存储引擎操做(若是适用)将合并为单个事务。

②:在DDL操做期间,SQL层没有中间提交。

③:在适用的状况下:

    数据字典,程序,事件和UDF高速缓存的状态与DDL操做的状态一致,这意味着更新高速缓存以反映DDL操做是成功完成仍是回滚。

    DDL操做中涉及的存储引擎方法不执行中间提交,而且存储引擎将自身注册为DDL事务的一部分。

    存储引擎支持DDL操做的重作和回滚,这在DDL操做的 Post-DDL阶段执行。

④:DDL操做的可见行为是原子的,这会更改某些DDL语句的行为

 

注意:

  原子或其余DDL语句隐式结束当前会话中处于活动状态的任何事务,就好像您COMMIT在执行语句以前完成了同样。这意味着DDL语句不能在另外一个事务中,在事务控制语句中执行 START TRANSACTION ... COMMIT,或者与同一事务中的其余语句结合使用。

 

三、DDL语句行为的变化

3.一、DROP TABLE:

 若是全部命名表都使用原子DDL支持的存储引擎,则操做是彻底原子的。该语句要么成功删除全部表,要么回滚。

DROP TABLE若是命名表不存在,而且未进行任何更改(不管存储引擎如何),则会失败并显示错误。以下所示:

 

mysql> CREATE TABLE t1 (c1 INT);

mysql> DROP TABLE t1, t2;

ERROR 1051 (42S02): Unknown table 'test.t2'

mysql> SHOW TABLES;

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

| Tables_in_test |

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

| t1             |

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

在引入原子DDL以前, DROP TABLE虽然会报错误表不存在,可是存在的表会被执行成功,以下:

mysql> CREATE TABLE t1 (c1 INT);

mysql> DROP TABLE t1, t2;

ERROR 1051 (42S02): Unknown table 'test.t2'

mysql> SHOW TABLES;

Empty set (0.00 sec)

 

注意:

   因为行为的这种变化,DROP TABLE会在 MySQL 5.7主服务器上的部分完成 语句在MySQL 8.0从服务器上复制时失败。要避免此故障情形,请在DROP TABLE语句中使用IF EXISTS语法以防止对不存在的表发生错误

 

3.二、DROP DATABASE:

   若是全部表都使用原子DDL支持的存储引擎,则为atomic。该语句要么成功删除全部对象,要么回滚。可是,从文件系统中删除数据库目录是最后一次,而且不是原子事务的一部分。若是因为文件系统错误或服务器暂停而致使数据库目录的删除失败, DROP DATABASE则不会回滚事务。

 

3.三、对于不使用原子DDL支持的存储引擎的表,表删除发生在原子 DROP TABLE或 DROP DATABASE事务以外。这样的表删除被单独写入二进制日志,这在中断DROP TABLE或 DROP DATABASE操做的状况下将存储引擎,数据字典和二进制日志之间的差别限制为最多一个表 。对于删除多个表的操做,不使用原子DDL支持的存储引擎的表将在执行以前删除。

 

3.四、CREATE TABLE, ALTER TABLE, RENAME TABLE, TRUNCATE TABLE, CREATE TABLESPACE,和 DROP TABLESPACE对使用原子DDL支持的存储引擎表执行的操做要么彻底提交或若是服务器的操做时中止回滚。在早期的MySQL版本中,这些操做的中断可能会致使存储引擎,数据字典和二进制日志之间的差别,或留下孤立文件。RENAME TABLE若是全部命名表都使用原子DDL支持的存储引擎,则操做只是原子操做。

 

3.五、DROP VIEW:

 若是命名视图不存在且未进行任何更改,则会失败。在此示例中演示了行为更改,其中 DROP VIEW语句失败,由于命名视图不存在,以下:

mysql> CREATE VIEW test.viewA AS SELECT * FROM t;

mysql> DROP VIEW test.viewA, test.viewB;

ERROR 1051 (42S02): Unknown table 'test.viewB'

mysql> SHOW FULL TABLES IN test WHERE TABLE_TYPE LIKE 'VIEW';

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

| Tables_in_test | Table_type |

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

| viewA          | VIEW       |

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

在引入原子DDL以前, 使用DROP VIEW删除视图会报错,可是存在的视图会被成功删除:

mysql> CREATE VIEW test.viewA AS SELECT * FROM t;

mysql> DROP VIEW test.viewA, test.viewB;

ERROR 1051 (42S02): Unknown table 'test.viewB'

mysql> SHOW FULL TABLES IN test WHERE TABLE_TYPE LIKE 'VIEW';

Empty set (0.00 sec)

 

注意:

   因为行为的这种变化,DROP VIEW在MySQL 5.7主服务器上的部分完成 操做在MySQL 8.0从服务器上复制时会失败。要避免此故障情形,请在DROP VIEW语句中使用IF EXISTS语法以防止对不存在的视图发生错误。

 

3.六、再也不容许部分执行账户管理声明。账户管理语句对全部命名用户成功或回滚,若是发生错误则无效。在早期的MySQL版本中,为多个用户命名的账户管理语句可能对某些用户成功,而对其余用户则失败。

以下:其中第二个CREATE USER 语句返回错误但失败,由于它没法对全部命名用户成功。

mysql> CREATE USER userA;

mysql> CREATE USER userA, userB;

ERROR 1396 (HY000): Operation CREATE USER failed for 'userA'@'%'

mysql> SELECT User FROM mysql.user WHERE User LIKE 'user%';

+-------+

| User  |

+-------+

| userA |

+-------+

在引入原子DDL以前,第二个 使用CREATE USER语句建立用户会返回一个错误,可是不存在的用户会成功建立,:

mysql> CREATE USER userA;

mysql> CREATE USER userA, userB;

ERROR 1396 (HY000): Operation CREATE USER failed for 'userA'@'%'

mysql> SELECT User FROM mysql.user WHERE User LIKE 'user%';

+-------+

| User  |

+-------+

| userA |

| userB |

+-------+

 

注意:

   因为行为的这种变化,MySQL 5.7主服务器上部分会成功执行,会在MySQL 8.0从服务器上复制时失败。要避免此故障情形,请在建立用户的命令中使用IF EXISTS或 IF NOT EXISTS语法,以防止与命名用户相关的错误。

 

四、存储引擎支持:目前只有innodb存储引擎支持原子DDL

   目前,只有InnoDB存储引擎支持原子DDL。不支持原子DDL的存储引擎免于DDL原子性。涉及豁免存储引擎的DDL操做仍然可以引入操做中断或仅部分完成时可能发生的不一致。

   要支持重作和回滚DDL操做, InnoDB请将DDL日志写入 mysql.innodb_ddl_log表,该表是驻留在mysql.ibd数据字典表空间中的隐藏数据字典表 。

要mysql.innodb_ddl_log在DDL操做期间查看写入表的DDL日志 ,请启用 innodb_print_ddl_logs 配置选项。

 

注意:

mysql.innodb_ddl_log不管innodb_flush_log_at_trx_commit 设置多少,对表的 更改的重作日志 都会当即刷新到磁盘 。当即刷新重作日志能够避免DDL操做修改数据文件的状况,可是mysql.innodb_ddl_log由这些操做产生的对表的更改的重作日志 不会持久保存到磁盘。这种状况可能会在回滚或恢复期间致使错误。

 

InnoDB存储引擎分阶段执行DDL操做。DDL操做 ALTER TABLE能够在Commit阶段以前屡次执行 Prepare和Perform阶段:

 

准备:建立所需对象并将DDL日志写入 mysql.innodb_ddl_log表中。DDL日志定义了如何前滚和回滚DDL操做。

执行:执行DDL操做。例如,为CREATE TABLE操做执行建立例程。

提交:更新数据字典并提交数据字典事务。

Post-DDL:重播并从mysql.innodb_ddl_log表中删除DDL日志。为了确保能够安全地执行回滚而不引入不一致性,在最后阶段执行文件操做,例如重命名或删除数据文件。这一阶段还从删除的动态元数据 mysql.innodb_dynamic_metadata的数据字典表DROP TABLE,TRUNCATE TABLE和该重建表其余DDL操做。

 

注意:

  不管事务是提交仍是回滚, DDL日志都会在Post-DDL阶段重播并从表中删除 。mysql.innodb_ddl_log若是服务器在DDL操做期间暂停,则DDL日志应仅保留在表中。在这种状况下,DDL日志将在恢复后重播并删除。

 

  在恢复状况下,能够在从新启动服务器时提交或回滚DDL事务。若是在重作日志和二进制日志中存在在DDL操做的提交阶段期间执行的数据字典事务,则 该操做被视为成功而且前滚。不然,在InnoDB重放数据字典重作日志时回滚不完整的数据字典事务 ,并回滚DDL事务。

 

五、查看DDL日志:

   InnoDB将DDL日志写入 mysql.innodb_ddl_log表以支持重作和回滚DDL操做。该 mysql.innodb_ddl_log表是隐藏在mysql.ibd数据字典表空间中的隐藏数据字典表 。与其余隐藏数据字典表同样,mysql.innodb_ddl_log在非调试版本的MySQL中没法直接访问该 表。

相关文章
相关标签/搜索