报错信息:
InnoDB: An optimized (without redo logging) DDLoperation has been performed. All modified pages may not have been flushed to the disk yet.
为了解决这个错误,percona新加了三个参数xtrabackup --lock-ddl, xtrabackup --lock-ddl-timeout, xtrabackup --lock-ddl-per-table。
MySQL5.7在记录redo log时会跳过某些DDL。在MySQL5.7当中,创建索引分为三个阶段
1:扫描clustered index,生成索引项到sort buffer当中,当sort buffer满了的时候,会写入到临时文件当中。
2:多个线程对临时文件或者sort buffer中的索引项进行排序
3:排序完成后插入到 B-tree当中。
在此之前,MySQL创建索引的时候会调用insert APIs逐条进行 B-tree的插入,这种插入方式会打开 B-tree游标,找到位置,乐观插入。如果要插入的 B-tree节点page页满了,就会拆分或者合并 B-tree的page页,我们称之为悲观插入。这样创建索引就会引起不断分裂和合并,并且还有查找插入位置,代价会比较昂贵。
Sorted Index Builds and Redo Logging:
在使用Sorted Index方式创建索引的时候会关闭掉Redo Logging,他是通过检查点的方式来保证创建索引的高可用性。检查点强制将所有脏页写入磁盘,在索引创建期间, page cleaner会定期的刷新脏页以保证检查点的快速前推。通常情况下,只有当干净页面的数量低于设置的阈值时,page cleaner才回去刷新脏页,但是在创建索引的过程中, page cleaner会快速刷新,来减少检查点的开销。
由于不记录redo,然后再备份时候就会出现以下错误
[FATAL] InnoDB: An optimized(without redo logging) DDLoperation has been performed. All modified pages may not have been flushed to the disk yet.
Percona XtraBackup will not be able to take a consistent backup. Retry the backup operation
xtrabackup为了解决这个问题加入了--lock-ddl选项,但是会在备份的时候会对所有表加一个备份锁(Executing LOCK TABLES FOR BACKUP)
另外一个选项是--lock-ddl-per-table,会有以下输出
170726 11:32:33 [01] Copying ./ibdata1 to /home/shahriyar.rzaev/backup_dir/ps_5.7_master/full/2017-07-26_11-31-56/ibdata1
170726 11:32:33 Locking MDL for db1.sb1
170726 11:32:33 [02] Copying ./db1/sb1.ibd to /home/shahriyar.rzaev/backup_dir/ps_5.7_master/full/2017-07-26_11-31-56/db1/sb1.ibd
170726 11:32:33 Locking MDL for db1.sbtest1
170726 11:32:33 Locking MDL for db2.sb1
170726 11:32:33 [03] Copying ./db1/sbtest1.ibd to /home/shahriyar.rzaev/backup_dir/ps_5.7_master/full/2017-07-26_11-31-56/db1/sbtest1.ibd
170726 11:32:33 [04] Copying ./db2/sb1.ibd to /home/shahriyar.rzaev/backup_dir/ps_5.7_master/full/2017-07-26_11-31-56/db2/sb1.ibd
170726 11:32:33 [04] ...done
170726 11:32:33 >> log scanned up to (2892754398)
170726 11:32:34 Locking MDL for db2.sbtest1
有一点需要注意是在非percona server使用--lock-ddl参数肯能不被支持,例如MariaDB。但是--lock-ddl-per-table是所有的server都支持的。
但是如果一个进程持有MDL锁,另外一个进程执行alter table操作(创建索引属于alter table操作),这时候更新操作就会被阻塞。
如果不想在备份时候又任何阻塞就只能打开old_alter_table参数,这样就不能使用alter table新特性。
参数项解释
--lock-ddl Issue LOCK TABLES FOR BACKUP if it is supported by server
at the beginning of the backup to block all DDL
operations.
--lock-ddl-timeout=#
If LOCK TABLES FOR BACKUP does not return within given
timeout, abort the backup.
--lock-ddl-per-table
Lock DDL for each table before xtrabackup starts to copy
it and until the backup is completed.
--safe-slave-backup Stop slave SQL thread and wait to start backup until
Slave_open_temp_tables in "SHOW STATUS" is zero. If there
are no open temporary tables, the backup will take place,
otherwise the SQL thread will be started and stopped
until there are no open temporary tables. The backup will
fail if Slave_open_temp_tables does not become zero after
--safe-slave-backup-timeout seconds. The slave SQL thread
will be restarted when the backup finishes.