10bet网址
MySQL 8.0参考手册
相关文件10bet官方网站 本手册下载 本手册摘录

MySQL 8.0参考手册/.../ 原子数据定义语句支持

13.1.1原子数据定义声明支持

MySQL 8.0支持原子数据定义语言(DDL)语句。这个特性被称为原子DDL.原子DDL语句将与DDL操作相关联的数据字典更新、存储引擎操作和二进制日志写入组合为单个原子操作。该操作要么被提交,并将适用的更改持久化到数据字典、存储引擎和二进制日志,要么被回滚,即使在操作期间服务器停止。

请注意

原子DDL不是交易DDL..DDL语句,无论是原子的还是其他的,都会隐式地结束当前会话中活动的任何事务,就好像您已经完成了一个提交在执行语句之前。这意味着DDL语句不能在另一个事务中执行,比如在事务控制语句中开始事务……提交,或与同一事务中的其他报表组合。

在MySQL 8.0中引入MySQL数据字典使得原子DDL成为可能。在早期的MySQL版本中,元数据存储在元数据文件、非事务性表和特定于存储引擎的字典中,这就需要中间提交。由MySQL数据字典提供的集中式、事务性元数据存储消除了这个障碍,使得将DDL语句操作重组为原子操作成为可能。

原子DDL特性将在本节的以下主题中进行描述:

支持的DDL陈述

原子DDL特性同时支持表和非表DDL语句。表相关的DDL操作需要存储引擎支持,而非表的DDL操作不需要。目前,只有Innodb.存储引擎支持原子DDL。

  • 支持的表DDL语句包括创造改变,更改, 和下降语句用于数据库、表空间、表和索引,以及截断表声明。

  • 支持的非表DDL语句包括:

    • 创造下降陈述,以及,如适用,改变,更改用于存储程序、触发器、视图和可加载函数的语句。

    • 账户管理报表:创造改变,更改下降,如适用,重命名用户和角色的陈述,以及格兰特撤销语句。

原子DDL特性不支持以下语句:

原子DDL特点

原子DDL语句的特征包括:

  • 元数据更新、二进制日志写入和存储引擎操作(在适用的情况下)被组合成单个原子操作。

  • 在DDL操作期间,SQL层没有中间提交。

  • 适用:

    • 数据字典、例程、事件和可加载函数缓存的状态与DDL操作的状态一致,这意味着缓存被更新,以反映DDL操作是否成功完成或回滚。

    • 涉及DDL操作的存储引擎方法不执行中间提交,并且存储引擎作为DDL操作的一部分寄存自身。

    • 存储引擎支持重做和回滚DDL操作,该操作是在此中执行的后DDL.阶段的DDL操作。

  • DDL操作的可见行为是原子性的,它会改变一些DDL语句的行为。看到DDL语句行为的变化

DDL语句行为的变化

本节描述由于引入原子DDL支持而导致的DDL语句行为的变化。

  • 删除表如果所有命名表都使用原子ddl支持的存储引擎,则操作是完全原子的。语句要么成功删除所有表,要么回滚。

    删除表如果命名表不存在,且无论存储引擎如何,都没有进行任何更改,则会失败并报错。行为中的这种变化在下面的示例中演示,其中删除表语句失败,因为命名表不存在:

    mysql> CREATE TABLE t1 (c1 INT);mysql> DROP TABLE t1, t2;错误1051(42s02):未知表'test.t2'mysql> show table;+----------------+ | Tables_in_test  | +----------------+ | t1  | +----------------+

    在引入原子DDL之前,删除表对于不存在的命名表报告错误,但是对于存在的命名表报告成功:

    mysql> CREATE TABLE t1 (c1 INT);mysql> DROP TABLE t1, t2;错误1051(42s02):未知表'test.t2'mysql> show table;空集(0.00秒)
    请注意

    由于这种行为的改变,部分完成删除表当在MySQL 8.0副本上复制时,在MySQL 5.7复制源服务器上的语句失败。要避免这种失败场景,请使用如果存在语法在删除表语句来防止不存在的表发生错误。

  • 删除数据库是原子的,如果所有表都使用原子的ddl支持的存储引擎。该语句要么成功删除所有对象,要么被回滚。但是,最后从文件系统删除数据库目录,这不是原子操作的一部分。如果由于文件系统错误或服务器停止导致删除数据库目录失败,则删除数据库事务没有回滚。

  • 对于不使用原子ddl支持的存储引擎的表,表删除发生在原子引擎之外删除表或者删除数据库事务。这样的表删除被单独写入二进制日志,这样在中断的情况下,存储引擎、数据字典和二进制日志之间的差异最多限制在一个表删除表或者删除数据库操作。对于删除多个表的操作,不使用原子ddl支持的存储引擎的表将在使用原子ddl支持的存储引擎的表之前删除。

  • 创建表ALTER TABLE重命名表截断表创建表空间, 和删除表空间对于使用原子ddl支持的存储引擎的表的操作,如果服务器在操作期间停止,则会完全提交或回滚。在早期的MySQL版本中,这些操作的中断可能会导致存储引擎、数据字典和二进制日志之间的差异,或者留下孤儿文件。重命名表如果所有命名表都使用一个受ddl支持的原子存储引擎,则操作只是原子的。

  • 从MySQL 8.0.21开始,在支持原子DDL的存储引擎上创建表……选择当使用基于行的复制时,语句被记录为二进制日志中的一个事务。以前,它被记录为两个事务,一个用于创建表,另一个用于插入数据。两个事务之间或插入数据时的服务器故障可能导致复制空表。通过引入原子DDL支持,创建表……选择现在对基于行的复制安全,并允许使用基于GTID的复制。

    在支持原子DDL和外键限制的存储引擎上,不允许创建外键创建表……选择在使用基于行的复制时。外键约束可以在以后使用ALTER TABLE

    创建表……选择作为原子操作应用时,在插入数据时将在表上持有元数据锁,这将在操作期间阻止对表的并发访问。

  • 删除视图如果指定视图不存在,且没有进行任何更改,则失败。在这个例子中演示了行为的改变,其中删除视图语句失败,因为不存在命名视图:

    mysql>创建视图test.viewa为select * from t;MySQL> Drop View Test.Viewa,test.ViewB;错误1051(42s02):未知表'test.viewb'mysql>在测试中显示完整表,其中table_type等'查看';+----------------+------------+ | Tables_in_test | Table_type  | +----------------+------------+ | viewA |视图  | +----------------+------------+

    在引入原子DDL之前,删除视图对于不存在的命名视图返回错误,但对于存在的命名视图返回成功:

    mysql>创建视图test.viewa为select * from t;MySQL> Drop View Test.Viewa,test.ViewB;错误1051(42s02):未知表'test.viewb'mysql>在测试中显示完整表,其中table_type等'查看';空集(0.00秒)
    请注意

    由于这种行为的改变,部分完成删除视图在MySQL 8.0副本上复制MySQL 5.7复制源服务器失败。要避免这种失败场景,请使用如果存在语法在删除视图语句来防止对不存在的视图发生错误。

  • 不再允许部分执行帐户管理报表。帐户管理语句对所有命名用户都成功,或者在发生错误时回滚,并且没有影响。在早期的MySQL版本中,命名多个用户的帐户管理语句可能对某些用户成功,对其他用户失败。

    在这个例子中演示了行为的改变,在第二个例子中创建用户语句返回错误但失败,因为它不能成功对所有命名用户。

    mysql> CREATE USER userera;mysql> CREATE USER userA, userB;ERROR 1396 (HY000): Operation CREATE USER failed for 'userA'@'%' mysql> SELECT USER FROM mysqluser WHERE user LIKE 'user%';+-------+ |用户| +-------+ | userA | +-------+

    在引入原子DDL之前,第二个创建用户如果指定用户不存在,则返回错误,但如果指定用户存在,则返回成功:

    mysql> CREATE USER userera;mysql> CREATE USER userA, userB;ERROR 1396 (HY000): Operation CREATE USER failed for 'userA'@'%' mysql> SELECT USER FROM mysqluser WHERE user LIKE 'user%';+-------+ | 用户  | +-------+ | userA | | userB  | +-------+
    请注意

    由于这种行为的改变,当在MySQL 8.0副本上复制时,在MySQL 5.7复制源服务器上部分完成的帐户管理语句失败。要避免这种失败场景,请使用如果存在或者如果不存在语法,酌情在帐户管理语句中,以防止与命名用户相关的错误。

存储引擎的支持

目前,只有Innodb.存储引擎支持原子DDL。不支持原子DDL的存储引擎不受DDL原子性的限制。涉及豁免存储引擎的DDL操作仍然能够引入不一致,当操作中断或仅部分完成时,可能会出现不一致。

支持重做和回滚DDL操作,Innodb.将DDL日志写入mysql.innodb_ddl_log对象中的隐藏数据字典表mysql.ibd数据字典表空间。

查看写入到mysql.innodb_ddl_log在DDL操作期间启用innodb_print_ddl_logs配置选项。有关更多信息,请参见DDL日志查看

请注意

的更改的重做日志mysql.innodb_ddl_log表将立即刷新到磁盘,而不管innodb_flush_log_at_trx_commit.设置。刷新重做日志可以立即避免数据文件被DDL操作修改,而重做日志用于更改mysql.innodb_ddl_log由这些操作产生的表不会持久化到磁盘。这种情况可能会在回滚或恢复期间导致错误。

Innodb.存储引擎在阶段执行DDL操作。DDL操作如ALTER TABLE可以执行准备履行阶段之前多次犯罪阶段。

  1. 准备:创建所需的对象并将DDL日志写入mysql.innodb_ddl_log表格DDL日志定义了如何前滚和回滚DDL操作。

  2. 履行:执行DDL操作。例如,执行创建例程创建表操作。

  3. 犯罪:更新数据字典并提交数据字典事务。

  4. 后DDL.:重放和删除DDL日志mysql.innodb_ddl_log表格为了确保可以安全地执行回滚而不会引入不一致,在此最终阶段执行诸如重命名或删除数据文件的文件操作。此阶段还从中删除动态元数据mysql.innodb_dynamic_metadata数据字典表删除表截断表,以及重建表的其他DDL操作。

DDL日志将被重放并从mysql.innodb_ddl_log表中的表后DDL.相位,无论DDL操作是如何承诺还是回滚。DDL日志应该只留在mysql.innodb_ddl_log表,如果服务器在DDL操作期间暂停。在这种情况下,DDL日志将在恢复后重新播放并删除。

在恢复情况下,可能会在服务器重新启动时提交或回滚DDL操作。操作期间执行的数据字典事务犯罪如果DDL操作的一个阶段出现在重做日志和二进制日志中,则认为该操作成功并被前滚。否则,不完整的数据字典事务将在何时回滚Innodb.重放数据字典重做日志,并回滚DDL操作。

DDL日志查看

查看写入到mysql.innodb_ddl_log数据字典表中涉及的原子DDL操作Innodb.存储引擎,启用innodb_print_ddl_logs让MySQL写入DDL日志stderr.根据主机操作系统和MySQL配置,stderr可能是错误日志、终端或控制台窗口。看到第5.4.2.2节,“默认错误日志目标配置”

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 unligned 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)collat​​e utf8_bin collat​​e utf8_bin,new_file_path varchar(512)collat​​e utf8_bin,key(thread_id));
  • id:用于DDL日志记录的唯一标识符。

  • thread_id.:为每条DDL日志记录分配一条thread_id.,用于重放和删除属于特定DDL操作的DDL日志。涉及多个数据文件操作的DDL操作会生成多条DDL日志记录。

  • 类型: DDL操作类型。类型包括免费的(删除索引树),删除(删除一个文件),重命名(重命名文件),或者下降(删除元数据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对于一个创建表操作。

mysql> set global innodb_print_ddl_logs = 1;MySQL>创建表T1(C1 INT)引擎= InnoDB;
[注释][000000]InnoDB: DDL log insert: [DDL record: DELETE SPACE, id=18, thread_id=7, space_id=5, old_file_path=./test/t1. log]日志插入[注释][000000]InnoDB: DDL log insert: [DDL record: REMOVE CACHE, id=19, thread_id=7, table_id=1058, new_file_path=test/t1][注释][000000]InnoDB: DDL log insert: [DDL record: REMOVE CACHE, id=19, thread_id=7, table_id=1058, new_file_path=test/t1][注释][000000]FREE, id=20, thread_id=7, space_id=5, index_id=132, page_no=4][注释][000000]InnoDB: DDL log delete: by id 20[注释][000000]InnoDB: DDL log post DDL: begin for thread id: 7[注释][000000]InnoDB: DDL log post DDL: end for thread id: 7