支持原子DDL语句,table导致的mysql事务回滚失败

   MySQL 8.0发端支持原子数据定义语言(DDL)语句。此功效称为原子DDL。原子DDL语句将与DDL操作关联的多少字典更新,存款和储蓄引擎操作和二进制日志写入组合到单个原子事务中。固然服务器在操作时期暂停,也会提交业务,并将适用的退换保留到数量字典,存款和储蓄引擎和二进制日志,大概回滚事务。

在MySQL8.0事先的版本中,由于架构的由来,mysql在server层使用统后生可畏的frm文件来囤积表元数据消息,这几个信息可以知道被分化的积攒引擎识别。而其实innodb本人也蕴藏有元数据音信。那给ddl带来了一定的挑衅,因为这种架构不可能做到ddl的原子化,大家在线上平日能够见到数据目录下遗留的偶然文件,只怕相像server层和innodb层列个数区别等之类的大谬不然。以至有个别ddl恐怕还遗留元数据在innodb内,而错失了frm,导致无能为力重新建立表…..(大家为了解决那些难题,实现了二个叫drop table force的效率,去强制做清理….)

几天前做多少迁移, 开掘事情一时候能够回滚, 有时候不可以回滚, 最后一小点调和开采中间有段修正表结构的口舌, 最终变成回滚退步。

 

(以下有所的座谈都假定使用InnoDB存储引擎)

 

   通过在MySQL 8.0中引进MySQL数据字典,能够完成Atomic DDL。在早期的MySQL版本中,元数据存款和储蓄在元数据文件,非事务性表和仓储引擎特定的字典中,那须求中间提交。MySQL数据字典提供的集日式事务元数据存款和储蓄肃清了这朝气蓬勃障碍,使得将DDL语句操作结合为原子事务成为恐怕。

到了8.0本子,大家领略全部的元数据现已合併用InnoDB来拓宽拘系,那就给贯彻原子ddl带来了说不定,差相当少全数的对innodb表,存款和储蓄进度,触发器,视图或然UDF的操作,都能完结原子化:

1.MySQL最常用的七个表类型: InnoDB和MyISAM。MyISAM类型的表重申的是性质,其执行数度比InnoDB类型越来越快,可是不提供业务补助,而InnoDB提供业务支持、存款和储蓄进程、视图、行级锁定等等高档数据库成效,若回滚失利,先反省表类型。 

 

- 元数据修改,binlog以及innodb的操作都放在一个事务中- 增加了一个内部隐藏的系统表`mysql.innodb_ddl_log`,ddl操作被记录到这个表中,注意对该表的操作产生的redo会fsync到磁盘上,而不会考虑innodb_flush_log_at_trx_commit的配置。当崩溃重启时,会根据事务是否提交来决定通过这张表的记录去回滚或者执行ddl操作- 增加了一个post-ddl的阶段,这也是ddl的最后一个阶段,会去:1. 真正的物理删除或重命名文件; 2. 删除innodb_ddl_log中的记录项; 3.对于一些ddl操作还会去更新其动态元数据信息(存储在`mysql.innodb_dynamic_metadata`,例如corrupt flag, auto_inc值等)- 一个正常运行的ddl结束后,其ddl log也应该被清理,如果这中间崩溃了,重启时会去尝试重放:1.如果已经走到最后一个ddl阶段的,就replay ddl log,把ddl完成掉;2. 如果处于某个中间态,则回滚ddl

SHOW ENGINES 语句可以查看当前的数据库扶植的积累类

法定文档:

出于引入了atomic ddl, 某些ddl操作的作为也时有产生了转移:

图片 1

- DROP TABLE: 在之前的版本中,一个drop table语句中如果要删多个表,比如t1,t2, t2不存在时,t1会被删除。但在8.0中,t1和t2都不会被删除,而是抛出错误。因此要注意5.7->8.0的复制问题 (DROP VIEW, CREATE USER也有类似的问题)- DROP DATABASE: 修改元数据和ddl_log先提交事务,而真正的物理删除数据文件放在最后,因此如果在删除文件时崩溃,重启时会根据ddl_log继续执行drop database

 

 

MySQL很恩爱的加了叁个增选innodb_print_ddl_logs,展开后大家可以从错误日志看见相应的ddl log,上面大家因此那个来看下一些一流ddl的历程

SHOW CREATE TABLE 表名;能够查看表的始建语句,最终有表的囤积结构

 

root@ 11:12:19>SET GLOBAL innodb_print_ddl_logs = 1; Query OK, 0 rows affected root@ 11:12:22>SET GLOBAL log_error_verbosity = 3; Query OK, 0 rows affected 

图片 2

1、支持的DDL语句

CREATE DATABASE

mysql> CREATE DATABASE test;Query OK, 1 row affected 

始建数据库语句未有写log_ddl,恐怕以为那不是累累操作,即使创立database的历程中小败了,重启后恐怕要求手动删除目录。

ALTE翼虎 TABLE 表名 ENGINE = InnoDB;校正表的积累类型

 原子DDL成效扶植表和非表DDL语句。与表相关的DDL操作要求仓库储存引擎支持,而非表DDL操作则无需。如今,独有InnoDB存储引擎帮忙原子DDL。

CREATE TABLE

mysql> USE test;Database changedmysql> CREATE TABLE t1 (a INT PRIMARY KEY, b INT);Query OK, 0 rows affected [InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=428, thread_id=7, space_id=76, old_file_path=./test/t1.ibd][InnoDB] DDL log delete : by id 428[InnoDB] DDL log insert : [DDL record: REMOVE CACHE, id=429, thread_id=7, table_id=1102, new_file_path=test/t1][InnoDB] DDL log delete : by id 429[InnoDB] DDL log insert : [DDL record: FREE, id=430, thread_id=7, space_id=76, index_id=190, page_no=4][InnoDB] DDL log delete : by id 430[InnoDB] DDL log post ddl : begin for thread id : 7InnoDB] DDL log post ddl : end for thread id : 7

从日记来看有三类操作,实际上描述了假使操作失败须要开展的三项逆向操作:删除数据文件,释放内部存款和储蓄器中的数量词典音讯,删除索引btree。在创立表此前,这一个多少被写入到ddl_log中,在成立完表并commit后,再从ddl log中去除那一个记录。别的上述日志中还也许有DDL log delete日记,其实在历次写入ddl log时是独自事务提交的,但在交付之后,会选拔当前事务实施一条delete操作,直到操作结束了才会交到。

 

 

加列

mysql> ALTER TABLE t1 ADD COLUMN c INT;Query OK, 0 rows affected Records: 0 Duplicates: 0 Warnings: 0[InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log post ddl : end for thread id : 7

留意这里实行的是Instant ddl, 那是8.0.13新支撑的表征,加列操作能够只改善元数据,由此从ddl log中没有必要记下数据

 

①:受帮衬的表DDL语句富含 CREATE,ALTELAND和 DROP对数据库,表,表和目录,以至讲话 TRUNCATE TABLE表明。

删列

mysql> ALTER TABLE t1 DROP COLUMN c;Query OK, 0 rows affected Records: 0 Duplicates: 0 Warnings: 0[InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=487, thread_id=7, space_id=83, old_file_path=./test/#sql-ib1108-1917598001.ibd][InnoDB] DDL log delete : by id 487[InnoDB] DDL log insert : [DDL record: REMOVE CACHE, id=488, thread_id=7, table_id=1109, new_file_path=test/#sql-ib1108-1917598001][InnoDB] DDL log delete : by id 488[InnoDB] DDL log insert : [DDL record: FREE, id=489, thread_id=7, space_id=83, index_id=200, page_no=4][InnoDB] DDL log delete : by id 489[InnoDB] DDL log insert : [DDL record: DROP, id=490, thread_id=7, table_id=1108][InnoDB] DDL log insert : [DDL record: RENAME SPACE, id=491, thread_id=7, space_id=82, old_file_path=./test/#sql-ib1109-1917598002.ibd, new_file_path=./test/t1.ibd][InnoDB] DDL log delete : by id 491[InnoDB] DDL log insert : [DDL record: RENAME TABLE, id=492, thread_id=7, table_id=1108, old_file_path=test/#sql-ib1109-1917598002, new_file_path=test/t1][InnoDB] DDL log delete : by id 492[InnoDB] DDL log insert : [DDL record: RENAME SPACE, id=493, thread_id=7, space_id=83, old_file_path=./test/t1.ibd, new_file_path=./test/#sql-ib1108-1917598001.ibd][InnoDB] DDL log delete : by id 493[InnoDB] DDL log insert : [DDL record: RENAME TABLE, id=494, thread_id=7, table_id=1109, old_file_path=test/t1, new_file_path=test/#sql-ib1108-1917598001][InnoDB] DDL log delete : by id 494[InnoDB] DDL log insert : [DDL record: DROP, id=495, thread_id=7, table_id=1108][InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=496, thread_id=7, space_id=82, old_file_path=./test/#sql-ib1109-1917598002.ibd][InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log replay : [DDL record: DELETE SPACE, id=496, thread_id=7, space_id=82, old_file_path=./test/#sql-ib1109-1917598002.ibd][InnoDB] DDL log replay : [DDL record: DROP, id=495, thread_id=7, table_id=1108][InnoDB] DDL log replay : [DDL record: DROP, id=490, thread_id=7, table_id=1108][InnoDB] DDL log post ddl : end for thread id : 7

那是个卓越的三等第ddl的进度:分为prepare, perform 以致commit多少个阶段:

  • Prepare: 那么些阶段会更改元数据,创造有的时候ibd文件#sql-ib1108-1917598001.ibd, 假使产生卓殊崩溃,大家供给能把那些有的时候文件删除掉, 因此和create table雷同,也为这么些idb写了三条日志:delete space, remove cache,以致free btree

  • Perform: 试行操作,将数据拷贝到上述ibd文件中,(同期管理online dmllog), 那有的不关乎log ddl操作

  • Commit: 更新数据词典新闻并付出业务, 这里会写几条日志:

    • DROP : table_id=1108
    • RENAME SPACE: #sql-ib1109-1917598002.ibd文件被rename成t1.ibd
    • RENAME TABLE: #sql-ib1109-1917598002被rename成t1
    • RENAME SPACE: t1.ibd 被rename成#sql-ib1108-1917598001.ibd
    • RENAME TABLE: t1表被rename成#sql-ib1108-1917598001
    • DROP TABLE: table_id=1108
    • DELETE SPACE: 删除#sql-ib1109-1917598002.ibd

实质上这一步写的ddl log描述了commit阶段操作的逆向进程:将t1.ibd rename成#sql-ib1109-1918598002, 并将sql-ib1108-一九二零598001 rename成t1表,最终删除旧表。在那之中删除旧表的操作这里不施行,而是到post-ddl阶段实行

  • Post-ddl: 在事情提交后,施行最后的操作:replay ddl log, 删除旧文件,清理mysql.innodb_dynamic_metadata中有关音信

    • DELETE SPACE: #sql-ib1109-1917598002.ibd
    • DROP: table_id=1108
    • DROP: table_id=1108

2.有个别时候有个别SQL语句会发出叁个隐式的交给操作,即实行到位这几个话语后,会有二个隐式的COMMIT操作。有以下SQL语句,不用你去“管”:

②:支持的非表DDL语句包含:

加索引

mysql> ALTER TABLE t1 ADD KEY;Query OK, 0 rows affected Records: 0 Duplicates: 0 Warnings: 0[InnoDB] DDL log insert : [DDL record: FREE, id=431, thread_id=7, space_id=76, index_id=191, page_no=5][InnoDB] DDL log delete : by id 431[InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log post ddl : end for thread id : 7

创造索引采取inplace创制的不二等秘书籍,未有偶尔文件,但万大器晚成那多少个发生的话,依旧亟待在爆发特别时清理临时索引, 因而扩张了一条FREE log,用于极度产生时亦可删除有的时候索引.

  • DDL语句,ALTER DATABASE、ALTER EVENT、ALTER PROCEDURE、ALTER TABLE、ALTER VIEW、CREATE TABLE、DROP TABLE、RENAME TABLE、TRUNCATE TABLE等;
  • 改革MYSQL架构的语句,CREATE USEEvoque、DROP USE福特Explorer、GRANT、RENAME USER、REVOKE、SET PASSWO福睿斯D;
  • 扣押语句,ANALYZE TABLE、CACHE INDEX、CHECK TABLE、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAI奥迪Q7 TABLE等

   CREATE和DROP 语句,以至(假如适用)ALTEPAJERO存款和储蓄程序,触发器,视图和客商定义函数(UDF)的言辞。

TRUNCATE TABLE

mysql> TRUNCATE TABLE t1;Query OK, 0 rows affected [InnoDB] DDL log insert : [DDL record: RENAME SPACE, id=439, thread_id=7, space_id=77, old_file_path=./test/#sql-ib1103-1917597994.ibd, new_file_path=./test/t1.ibd][InnoDB] DDL log delete : by id 439[InnoDB] DDL log insert : [DDL record: DROP, id=440, thread_id=7, table_id=1103][InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=441, thread_id=7, space_id=77, old_file_path=./test/#sql-ib1103-1917597994.ibd][InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=442, thread_id=7, space_id=78, old_file_path=./test/t1.ibd][InnoDB] DDL log delete : by id 442[InnoDB] DDL log insert : [DDL record: REMOVE CACHE, id=443, thread_id=7, table_id=1104, new_file_path=test/t1][InnoDB] DDL log delete : by id 443[InnoDB] DDL log insert : [DDL record: FREE, id=444, thread_id=7, space_id=78, index_id=194, page_no=4][InnoDB] DDL log delete : by id 444[InnoDB] DDL log insert : [DDL record: FREE, id=445, thread_id=7, space_id=78, index_id=195, page_no=5][InnoDB] DDL log delete : by id 445[InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log replay : [DDL record: DELETE SPACE, id=441, thread_id=7, space_id=77, old_file_path=./test/#sql-ib1103-1917597994.ibd][InnoDB] DDL log replay : [DDL record: DROP, id=440, thread_id=7, table_id=1103][InnoDB] DDL log post ddl : end for thread id : 7

Truncate table是个相比有趣的话题,在开始的一段时期5.6及此前的版本中, 是通过删除旧表创造新表的主意来实行的,5.7今后为了保险原子性,改成了原地truncate文件,同时扩张了三个truncate log文件,假设在truncate进程中垮台,能够通过这些文件在崩溃苏醒时再次truncate。到了8.0版本,又恢复生机成了删除旧表,创设新表的模式,与后面分裂的是,8.0版本在崩溃时得以回滚到旧数据,并非重复施行。以上述为例,主要包罗多少个步骤:

  • 将表t1.ibd rename成#sql-ib1103-1917597994.ibd
  • 创办新文件t1.ibd
  • post-ddl: 将老文件#sql-ib1103-1917597994.ibd删除

安顿事务时,不应包蕴这类语句。假设在作业的前部中宣布了三个无法被回滚的话语,则后部的别的语句会发生错误,在这里些意况下,通过宣布ROLLBACK语句不能回滚事务的大器晚成体功力。

   账户管理语句: CREATE,ALTE福特Explorer, DROP,,若是适用, RENAME报表客商和剧中人物,以致GRANT 和REVOKE报表。

RENAME TABLE

mysql> RENAME TABLE t1 TO t2;Query OK, 0 rows affected 

DDL LOG:

[InnoDB] DDL log insert : [DDL record: RENAME SPACE, id=450, thread_id=7, space_id=78, old_file_path=./test/t2.ibd, new_file_path=./test/t1.ibd][InnoDB] DDL log delete : by id 450[InnoDB] DDL log insert : [DDL record: RENAME TABLE, id=451, thread_id=7, table_id=1104, old_file_path=test/t2, new_file_path=test/t1][InnoDB] DDL log delete : by id 451[InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log post ddl : end for thread id : 7

其黄金时代就比较轻便了,只供给记录rename space 和rename table的逆操作即可. post-ddl无需狠抓在的操作

 

 

DROP TABLE

DROP TABLE t2

[InnoDB] DDL log insert : [DDL record: DROP, id=595, thread_id=7, table_id=1119][InnoDB] DDL log insert : [DDL record: DELETE SPACE, id=596, thread_id=7, space_id=93, old_file_path=./test/t2.ibd][InnoDB] DDL log post ddl : begin for thread id : 7[InnoDB] DDL log replay : [DDL record: DELETE SPACE, id=596, thread_id=7, space_id=93, old_file_path=./test/t2.ibd][InnoDB] DDL log replay : [DDL record: DROP, id=595, thread_id=7, table_id=1119][InnoDB] DDL log post ddl : end for thread id : 7

先在ddl log中记录下须求删除的数据,再交由后,再最后post-ddl阶段实行真正的删除表对象和文件操作

重在实今世码聚集在文书storage/innobase/log/log0ddl.cc中,包罗了向log_ddl表中插入记录以至replay的逻辑。

隐藏的innodb_log_ddl表结构如下

 def->add_field(0, "id", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT"); def->add_field(1, "thread_id", "thread_id BIGINT UNSIGNED NOT NULL"); def->add_field(2, "type", "type INT UNSIGNED NOT NULL"); def->add_field(3, "space_id", "space_id INT UNSIGNED"); def->add_field(4, "page_no", "page_no INT UNSIGNED"); def->add_field(5, "index_id", "index_id BIGINT UNSIGNED"); def->add_field(6, "table_id", "table_id BIGINT UNSIGNED"); def->add_field(7, "old_file_path", "old_file_path VARCHAR COLLATE UTF8_BIN"); def->add_field(8, "new_file_path", "new_file_path VARCHAR COLLATE UTF8_BIN"); def->add_index(0, "index_pk", "PRIMARY KEY; def->add_index(1, "index_k_thread_id", "KEY(thread_id)");

 

1.1、原子DDL效率不扶持以下语句:

笔录类型

传闻不一样的操作类型,能够分为如下几类:

  1. FREE_TREE_LOG目标是释放索引btree,入口函数log_DDL::write_free_tree_log,在开立索引和删除表时会调用到

对于drop table中关系的删索引操作,log ddl的插入操作放到父事务中,一齐只怕提交要么回滚对于开创索引的case, log ddl就要求单独提交,父事务将记录标记删除,那样前面假设ddl回滚了,也能将残存的index删掉。

  1. DELETE_SPACE_LOG

入口函数:Log_DDL::write_delete_space_log

用于记录删除tablespace操作,近似分为二种状态:

  1. drop table/tablespace, 写入的笔录随父事务一齐付出,并在post-ddl阶段replay
  2. 成立tablespace, 写入的记录单独提交,并被父事务标识删除,要是父事务回滚,就由此replay删除加入的tablespace
  3. RENAME_SPACE_LOG

入口函数:Log_DDL::write_rename_space_log

用以记录rename操作,比方假使我们把表t1 rename成t2,在中间就记下了逆向操作t2 rename to t1.在函数Fil_shard::space_rename()中,总是先写ddl log, 再做真正的rename操作. 写日记的历程相疑似独立工作提交,父事务做未提交的去除操作

  1. DROP_LOG

入口函数: Log_DDL::write_drop_log

用于记录删除表对象操作,这里不涉及文件层操作,写ddl log在父事务中推行

  1. RENAME_TABLE_LOG

入口函数: Log_DDL::write_rename_table_log

用以记录rename table对象的逆操作,和rename space相近,也是独立专门的学问提交ddl log, 父事务标志删除

  1. REMOVE_CACHE_LOG

入口函数: Log_DDL::write_remove_cache_log

用以拍卖内部存款和储蓄器表对象的清理,独立工作提交,父事务标识删除

  1. ALTER_ENCRYPT_TABLESPACE_LOG

入口函数: Log_DDL::write_alter_encrypt_space_log

用来记录对tablespace加密属性的校勘,独立事务提交. 在写完ddl log后改良tablespace page0 中的加密标记

综上,在ddl的进度中大概会付出数次事情,大致分为三类:

  • 单独工作写ddl log并交给,父事务标志删除, 假若父事务提交了,ddl log也被有意或是无意删除了,假使父事务回滚了,那将要凭借ddl log做逆操作来回滚ddl
  • 单身业务写ddl log 并交付, (近日独有ALTEWrangler_ENCRYPT_TABLESPACE_LOG)
  • 利用父事务写ddl log,在ddl停止时交由。供给在post-ddl阶段管理

MySQL 数据表主要支撑二种档案的次序,分别是:BDB、HEAP、ISAM、ME宝马7系GE、MYISAM、InnoBDB。

①:涉及除存款和储蓄引擎之外的蕴藏引擎的与表相关的DDL语句InnoDB。

post_ddl

总的来讲,有个别ddl log是随着父事务一齐付给的,有个别则在post-ddl阶段再进行, post_ddl发生在父事提交或回滚之后: 若事务回滚,根据ddl log做逆操作,若事务提交,在post-ddl阶段做最后真的不可逆操作

入口函数: Log_DDL::post_ddl -->Log_DDL::replay_by_thread_id

依附奉行ddl的线程thread id通过innodb_log_ddl表上的二级索引,找到log id,再到集中索引上找到其相应的记录项,然后再replay这么些操作,实现ddl后,清理对应记录

那三种又分为两类,黄金年代类是“事务安全型”(transaction-safe),包含BDB和InnoDB;其余都属于第二类,称为”非事务安全型”(non-transaction-safe)。

②:INSTALL PLUGIN和 UNINSTALL PLUGIN 陈述。

崩溃复苏

在崩溃苏醒结束后,会调用ha_post_recover接口函数,进而调用innodb内的函数Log_DDL::recover(), 相符的replay当中的笔录,并在甘休后去除记录。但ALTE昂Cora_ENCRYPT_TABLESPACE_LOG类型并非在这里一步删除,而是到场到三个数组ts_encrypt_ddl_records中,在之后调用resume_alter_encrypt_tablespace来还原操作,

难点消除:

③:INSTALL COMPONENT和 UNINSTALL COMPONENT 陈述。

参照文书档案

  1. 官方文书档案2. wl#9536: support crash safe ddl

本文小编:zhaiwx_yinfeng

阅读原来的小说

本文为云栖社区原创内容,未经同意不得转发。

  存款和储蓄引擎说白了就是怎么存款和储蓄数据、怎么样为存款和储蓄的多少创建目录和哪些校勘、查询数据等才具的得以完结模式。因为在论及数据库中数量的仓库储存是以表的格局积存的,所以存款和储蓄引擎也得以称作表类型(即存款和储蓄和操作此表的品类)。

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

InnoDB 是较新的事务安全型存款和储蓄引擎,用于事务管理应用程序,帮助BDB的大致具备天性,并具有众多新特色,饱含ACID事务扶助。

 

特性:

2、原子DDL特性:

事务管理机制 
支持外链 
崩溃后能立时过来 
协理外键成效,级联删除 
支撑并发手艺 
在硬盘上的存款和储蓄方式:InnoBDB frm

①:元数据更新,二进制日志写入和存款和储蓄引擎操作(借使适用)将联合为单个事务。

最新版本的Mysql已经安排移除对BDB的补助,转而用尽了全力前行InnoDB。InnoDB对Mysql有越来越好的特点帮衬,何况开拓社区活泼。

②:在DDL操作时期,SQL层未有中间提交。

  MyISAM 暗中认可的MySQL插件式存款和储蓄引擎,它是基于ISAM类型,但它扩展了数不清实用的扩展,它是在Web、数据存款和储蓄和其余应用境遇下最常使用的存款和储蓄引擎之一。注意,通过转移STORAGE_ENGINE配置变量,能够有助于地更改MySQL服务器的暗中认可存款和储蓄引擎。 
优点:

③:在适用的状态下:

1.比ISAM表更加小,所占能源越来越少 
2.方可在分歧平台间二进制移植表的类型在成立表时内定。

    数据字典,程序,事件和UDF高速缓存的情事与DDL操作的情事同样,那代表更新的高峰速缓存以彰显DDL操作是水到渠成做到或许回滚。

    DDL操作中涉嫌的积攒引擎方法不实践中间提交,并且存款和储蓄引擎将自身注册为DDL事务的大器晚成部分。

    存款和储蓄引擎帮助DDL操作的重做和回滚,那在DDL操作的 Post-DDL阶段实行。

④:DDL操作的可以预知行为是原子的,那会改动某个DDL语句的表现

 

注意:

  原子或任何DDL语句隐式甘休如今对话中居于活动状态的别样专业,就像你COMMIT在施行语句早先到位了相通。这表示DDL语句不能够在另八个思想政治工作中,在业务调节语句中实行START TRANSACTION ... COMMIT,大概与同等业务中的其余语句结合使用。

 

3、DDL语句行为的变通

3.1、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.2、DROP DATABASE:

   假设具有表都使用原子DDL帮忙的积存引擎,则为atomic。该语句要么成功删除全数指标,要么回滚。不过,从文件系统中剔除数据库目录是最终三次,况兼不是原子事务的黄金时代有的。假若出于文件系统错误或服务器暂停而产生数据库目录的删减战败, DROP DATABASE则不会回滚事务。

 

3.3、对于不应用原子DDL协助的积存引擎的表,表删除产生在原子 DROP TABLE或 DROP DATABASE事务之外。那样的表删除被单独写入二进制日志,那在制动踏板DROP TABLE或 DROP DATABASE操作的气象下将积攒引擎,数据字典和二进制日志之间的差异节制为最多二个表 。对于删除多少个表的操作,不应用原子DDL援助的积攒引擎的表将要奉行在此以前删除。

 

3.4、CREATE TABLE, ALTECRUISER TABLE, RENAME TABLE, TRUNCATE TABLE, CREATE TABLESPACE,和 DROP TABLESPACE对应用原子DDL帮忙的积累引擎表试行的操作照旧完全交给或只要服务器的操作时停下回滚。在中期的MySQL版本中,那么些操作的中断大概会促成存款和储蓄引擎,数据字典和二进制日志之间的差距,或留下孤立文件。RENAME TABLE就算全部命名表都施用原子DDL扶助的积累引擎,则操作只是原子操作。

 

3.5、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.6、不再允许有的举办帐户处理注解。帐户管理语句对具备命名客户成功或回滚,若是产生错误则不行。在前期的MySQL版本中,为多个客商命名的帐户管理语句恐怕对一些顾客成功,而对其余顾客则失利。

如下:在那之中第三个CREATE USE中华V语句重临错误但未果,因为它不可能对负有命名客商成功。

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以前,第3个 使用CREATE USETiguan语句成立客户会再次来到贰个不当,不过不设有的客户会水到渠成创办,:

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语法,防止备与命名顾客相关的大错特错。

 

4、存款和储蓄引擎支持:最近独有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事务。

 

5、查看DDL日志:

   InnoDB将DDL日志写入 mysql.innodb_ddl_log表以协助重做和回滚DDL操作。该 mysql.innodb_ddl_log表是隐形在mysql.ibd数据字典表空间中的隐敝数据字典表 。与别的掩盖数据字典表相符,mysql.innodb_ddl_log在非调节和测量试验版本的MySQL中不恐怕直接访问该 表。

本文由星彩网app下载发布于星彩彩票app下载,转载请注明出处:支持原子DDL语句,table导致的mysql事务回滚失败

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。