MySQL备份可能遇到的坑

时间:2023-03-09 03:04:58
MySQL备份可能遇到的坑

MySQL备份工具,支持各种参数选项,使用不同的选项极有可能影响备份处理过程。本文使用我们常规认为合理的备份参数,测试/验证是否存在容易忽视的坑

# 常规备份参数
# mysqldump
shell> mysqldump --single-transaction --master-data= -B replcrash >dbname_dump_serverid_`date +%Y%m%d`.sql # mysqlpump
shell> mysqlpump --single-transaction -B replcrash >dbname_pump_serverid_`date +%Y%m%d`.sql # mydumper
shell> mydumper -B replcrash -o /data/backup/mydumper # XtraBackup
# backup
shell> innobackupex [--defaults-file=MY.CNF] BACKUP-ROOT-DIR
# apply-log
shell> innobackupex --apply-log [--defaults-file=MY.CNF] BACKUP-DIR
# copy-back
shell> innobackupex --copy-back [--defaults-file=MY.CNF] BACKUP-DIR

常规备份参数

官方社区版MySQL 5.7.19 基于Row+Position搭建的一主一从异步复制结构:Master->{Slave}

ROLE HOSTNAME BASEDIR DATADIR IP PORT
Master ZST1 /usr/local/mysql /data/mysql/mysql3306/data 192.168.85.132 3306
Slave ZST1 /usr/local/mysql /data/mysql/mysql3308/data 192.168.85.132 3308

每次使用备份文件还原数据库后,重新搭建这个复制结构
备份工具版本:mysqldump、mysqlpump是MySQL 5.7.19中自带的;mydumper version 0.9.3、innobackupex version 2.4.8

一、mysqldump

1.1、DML操作对备份的影响

创建两张测试表

# 创建两张测试表(192.168.85.132,3306)
use replcrash;
create table py_user_innodb(
uid int not null auto_increment,
name varchar(32),
add_time datetime default current_timestamp,
server_id varchar(10),
primary key(uid),
key(name)
)engine=innodb; create table py_user_myisam(
uid int not null auto_increment,
name varchar(32),
add_time datetime default current_timestamp,
server_id varchar(10),
primary key(uid),
key(name)
)engine=myisam;

运行下面的脚本持续往测试表中写入数据

#!/user/bin/python
import string
import random
import MySQLdb
import time conn = MySQLdb.connect(host='192.168.85.132',
port=3306,
user='mydba',
passwd='mysql5719',
db='replcrash')
"""
create table py_user(
uid int not null auto_increment,
name varchar(32),
add_time datetime default current_timestamp,
server_id varchar(10),
primary key(uid),
key(name)
);
"""
while True:
r_name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(20,30)))
print r_name cursor = conn.cursor()
cursor.execute("insert into py_user_myisam(name,add_time,server_id) values('%s',now(),@@server_id);" % str(r_name))
cursor.execute("insert into py_user_innodb(name,add_time,server_id) values('%s',now(),@@server_id);" % str(r_name))
conn.commit()
time.sleep(0.001)

Python DML

开启general_log,用来查看mysqldump执行过程

# 开启general_log
mydba@192.168.85.132, [replcrash]> set global general_log_file='/data/mysql/mysql3306/data/mysql-general.log';
mydba@192.168.85.132, [replcrash]> set global general_log=;
# 清空general_log
[root@ZST1 logs]# cat /dev/null > /data/mysql/mysql3306/data/mysql-general.log # 备份replcrash数据库
[root@ZST1 backup]# mysqldump -h127.0.0. -P3306 -uroot -p --single-transaction --master-data= replcrash >/data/backup/replcrash_dump_1323306_`date +%Y%m%d`.sql

使用备份文件搭建复制

# 还原实例清空GTID信息
mydba@192.168.85.132, [replcrash]> reset master;
# 还原数据
[root@ZST1 backup]# mysql -h127.0.0. -P3308 -uroot -p replcrash </data/backup/replcrash_dump_1323306_`date +%Y%m%d`.sql # 搭建复制
mydba@192.168.85.132, [replcrash]> change master to
master_host='192.168.85.132',
master_port=,
master_user='repl',
master_password='repl',
master_auto_position=; # 启动复制,查看复制状态
mydba@192.168.85.132, [replcrash]> start slave;
mydba@192.168.85.132, [replcrash]> show slave status\G
*************************** . row ***************************
Master_Log_File: mysql-bin.
Read_Master_Log_Pos:
Relay_Log_File: relay-bin.
Relay_Log_Pos:
Relay_Master_Log_File: mysql-bin.
Slave_IO_Running: Yes
Slave_SQL_Running: No
Exec_Master_Log_Pos:
Last_SQL_Errno:
Last_SQL_Error: Could not execute Write_rows event on table replcrash.py_user_myisam; Duplicate entry '' for key 'PRIMARY', Error_code: ; handler error HA_ERR_FOUND_DUPP_KEY; the event''s master log mysql-bin., end_log_pos
Retrieved_Gtid_Set: 8ab82362-9c37-11e7-a858-000c29c1025c:-
Executed_Gtid_Set: 8ab82362-9c37-11e7-a858-000c29c1025c:-
Auto_Position:

从上面的结果中可以看到,主键冲突了,在从库查询一下这个表中大于等于冲突key的数据

# 查询从库出错表大于等于冲突key的数据
mydba@192.168.85.132,3308 [replcrash]> select * from replcrash.py_user_myisam where uid>=332;
+-----+--------------------------------+---------------------+-----------+
| uid | name | add_time | server_id |
+-----+--------------------------------+---------------------+-----------+
| 332 | X1LME9HO5V7WXNOKBVZE | 2018-01-02 09:05:07 | 1323306 |
| 333 | 2PBFQ7KS4BPIJ27G88EYXWEDSX5 | 2018-01-02 09:05:07 | 1323306 |
| 334 | E85Y2SS9UD0FZG4YGCNTRSWA8L | 2018-01-02 09:05:07 | 1323306 |
| 335 | Y2TQOEVJ58NN7EREL4WRZ | 2018-01-02 09:05:07 | 1323306 |
| 336 | O0MEATAXYIAE2V2IZG96YVQ56WEUHF | 2018-01-02 09:05:07 | 1323306 |
| 337 | A6QKRWEXHRGUA3V2CH61VXUNBVA3H2 | 2018-01-02 09:05:07 | 1323306 |
| 338 | NYCSI1HS61BN6QAVVYTZSC | 2018-01-02 09:05:07 | 1323306 |
| 339 | 7CFC1JQPIQGNC97MDTT8ZIMIZL7D | 2018-01-02 09:05:07 | 1323306 |
| 340 | GA78AR4Z12WQTEAM41JB | 2018-01-02 09:05:07 | 1323306 |
+-----+--------------------------------+---------------------+-----------+
9 rows in set (0.08 sec)

我们查看mysqldump备份文件获取的binlog pos

[root@ZST1 backup]# more replcrash_dump_1323306_20180102.sql
-- GTID state at the beginning of the backup
SET @@GLOBAL.GTID_PURGED='8ab82362-9c37-11e7-a858-000c29c1025c:1-251873';
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000183', MASTER_LOG_POS=;
[root@ZST1 backup]#

这里的pos信息是mysqldump通过SHOW MASTER STATUS获取。查看mysqldump得到的general-log;

[root@ZST1 data]# vim /data/mysql/mysql3306/data/mysql-general.log
...
--02T01::.693104Z Query FLUSH /*!40101 LOCAL */ TABLES
--02T01::.694738Z Query insert into py_user_myisam(name,add_time,server_id) values('7ATZSNFNIBW5DZNMNZYBMV',now(),@@server_id)
--02T01::.701616Z Query insert into py_user_innodb(name,add_time,server_id) values('7ATZSNFNIBW5DZNMNZYBMV',now(),@@server_id)
--02T01::.702139Z Query FLUSH TABLES WITH READ LOCK
--02T01::.702344Z Query commit
--02T01::.702411Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--02T01::.702597Z Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
--02T01::.702721Z Query SHOW VARIABLES LIKE 'gtid\_mode'
--02T01::.713019Z Query SELECT @@GLOBAL.GTID_EXECUTED
--02T01::.713179Z Query SHOW MASTER STATUS
--02T01::.725821Z Query UNLOCK TABLES
--02T01::.732125Z Query insert into py_user_myisam(name,add_time,server_id) values('X1LME9HO5V7WXNOKBVZE',now(),@@server_id)
--02T01::.733237Z Query insert into py_user_innodb(name,add_time,server_id) values('X1LME9HO5V7WXNOKBVZE',now(),@@server_id)
--02T01::.734240Z Query commit
--02T01::.740508Z Query SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL AND LOGFILE_GROUP_NAME IS NOT NULL AND LOGFILE_GROUP_NAME IN (SELECT DISTINCT LOGFILE_GROUP_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' AND TABLESPACE_NAME IN (SELECT DISTINCT TABLESPACE_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA IN ('replcrash'))) GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE, TOTAL_EXTENTS, INITIAL_SIZE ORDER BY LOGFILE_GROUP_NAME
--02T01::.741895Z Query insert into py_user_myisam(name,add_time,server_id) values('2PBFQ7KS4BPIJ27G88EYXWEDSX5',now(),@@server_id)
--02T01::.742720Z Query insert into py_user_innodb(name,add_time,server_id) values('2PBFQ7KS4BPIJ27G88EYXWEDSX5',now(),@@server_id)
--02T01::.743257Z Query commit
--02T01::.749840Z Query insert into py_user_myisam(name,add_time,server_id) values('E85Y2SS9UD0FZG4YGCNTRSWA8L',now(),@@server_id)
--02T01::.750588Z Query insert into py_user_innodb(name,add_time,server_id) values('E85Y2SS9UD0FZG4YGCNTRSWA8L',now(),@@server_id)
--02T01::.750989Z Query commit
--02T01::.754180Z Query SELECT DISTINCT TABLESPACE_NAME, FILE_NAME, LOGFILE_GROUP_NAME, EXTENT_SIZE, INITIAL_SIZE, ENGINE FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' AND TABLESPACE_NAME IN (SELECT DISTINCT TABLESPACE_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA IN ('replcrash')) ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
--02T01::.756229Z Query insert into py_user_myisam(name,add_time,server_id) values('Y2TQOEVJ58NN7EREL4WRZ',now(),@@server_id)
--02T01::.757030Z Query insert into py_user_innodb(name,add_time,server_id) values('Y2TQOEVJ58NN7EREL4WRZ',now(),@@server_id)
--02T01::.757598Z Query commit
--02T01::.763629Z Query insert into py_user_myisam(name,add_time,server_id) values('O0MEATAXYIAE2V2IZG96YVQ56WEUHF',now(),@@server_id)
--02T01::.764626Z Query insert into py_user_innodb(name,add_time,server_id) values('O0MEATAXYIAE2V2IZG96YVQ56WEUHF',now(),@@server_id)
--02T01::.765654Z Query commit
--02T01::.766769Z Query SHOW VARIABLES LIKE 'ndbinfo\_version'
--02T01::.773997Z Query insert into py_user_myisam(name,add_time,server_id) values('A6QKRWEXHRGUA3V2CH61VXUNBVA3H2',now(),@@server_id)
--02T01::.774757Z Query insert into py_user_innodb(name,add_time,server_id) values('A6QKRWEXHRGUA3V2CH61VXUNBVA3H2',now(),@@server_id)
--02T01::.775198Z Query commit
--02T01::.779582Z Query insert into py_user_myisam(name,add_time,server_id) values('NYCSI1HS61BN6QAVVYTZSC',now(),@@server_id)
--02T01::.780174Z Init DB replcrash
--02T01::.780249Z Query SAVEPOINT sp
--02T01::.780913Z Query insert into py_user_innodb(name,add_time,server_id) values('NYCSI1HS61BN6QAVVYTZSC',now(),@@server_id)
--02T01::.781387Z Query commit
--02T01::.781776Z Query show tables
--02T01::.782078Z Query show table status like 'py\_user'
--02T01::.782400Z Query SET SQL_QUOTE_SHOW_CREATE=
--02T01::.782513Z Query SET SESSION character_set_results = 'binary'
--02T01::.787051Z Query insert into py_user_myisam(name,add_time,server_id) values('7CFC1JQPIQGNC97MDTT8ZIMIZL7D',now(),@@server_id)
--02T01::.787810Z Query insert into py_user_innodb(name,add_time,server_id) values('7CFC1JQPIQGNC97MDTT8ZIMIZL7D',now(),@@server_id)
--02T01::.788502Z Query commit
--02T01::.788774Z Query show create table `py_user`
--02T01::.789570Z Query SET SESSION character_set_results = 'utf8'
--02T01::.789725Z Query show fields from `py_user`
--02T01::.790423Z Query show fields from `py_user`
--02T01::.791163Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user`
--02T01::.791447Z Query SET SESSION character_set_results = 'binary'
--02T01::.791648Z Query use `replcrash`
--02T01::.791778Z Query select @@collation_database
--02T01::.791929Z Query SHOW TRIGGERS LIKE 'py\_user'
--02T01::.792383Z Query SET SESSION character_set_results = 'utf8'
--02T01::.792492Z Query ROLLBACK TO SAVEPOINT sp
--02T01::.792651Z Query show table status like 'py\_user\_innodb'
--02T01::.792874Z Query SET SQL_QUOTE_SHOW_CREATE=
--02T01::.792948Z Query SET SESSION character_set_results = 'binary'
--02T01::.793024Z Query show create table `py_user_innodb`
--02T01::.793131Z Query SET SESSION character_set_results = 'utf8'
--02T01::.793220Z Query show fields from `py_user_innodb`
--02T01::.793607Z Query show fields from `py_user_innodb`
--02T01::.793985Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user_innodb`
--02T01::.794435Z Query insert into py_user_myisam(name,add_time,server_id) values('GA78AR4Z12WQTEAM41JB',now(),@@server_id)
--02T01::.795204Z Query insert into py_user_innodb(name,add_time,server_id) values('GA78AR4Z12WQTEAM41JB',now(),@@server_id)
--02T01::.795688Z Query commit
--02T01::.798108Z Query SET SESSION character_set_results = 'binary'
--02T01::.798205Z Query use `replcrash`
--02T01::.798303Z Query select @@collation_database
--02T01::.798408Z Query SHOW TRIGGERS LIKE 'py\_user\_innodb'
--02T01::.798884Z Query SET SESSION character_set_results = 'utf8'
--02T01::.798965Z Query ROLLBACK TO SAVEPOINT sp
--02T01::.799049Z Query show table status like 'py\_user\_myisam'
--02T01::.799271Z Query SET SQL_QUOTE_SHOW_CREATE=
--02T01::.799344Z Query SET SESSION character_set_results = 'binary'
--02T01::.799420Z Query show create table `py_user_myisam`
--02T01::.799554Z Query SET SESSION character_set_results = 'utf8'
--02T01::.799661Z Query show fields from `py_user_myisam`
--02T01::.800098Z Query show fields from `py_user_myisam`
--02T01::.800418Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user_myisam`

mysqldump备份过程(--single-transaction --master-data):
会话先执行FTWRL(实例只读),然后设置RR隔离级别->START TRANSACTION WITH CONSISTENT SNAPSHOT;->SHOW MASTER STATUS;->UNLOCK TABLES;->SELECT /*!40001 SQL_NO_CACHE */ * FROM `tbname`;
在UNLOCK TABLES解锁后其他事务就可以进行写入操作。general-log中我们可看到 UNLOCK TABLES 到 SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user_myisam` 之间往py_user_myisam、py_user_innodb各写入9条数据
SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user_innodb`;读取的是START TRANSACTION WITH CONSISTENT SNAPSHOT建立时的数据
SELECT /*!40001 SQL_NO_CACHE */ * FROM `py_user_myisam`;读取的是最新的数据
再来查看上述过程期间binary log记录

[root@ZST1 logs]# mysqlbinlog -vv --base64-output=decode-rows mysql-bin. |more
...
COMMIT/*!*/;
# at
# :: server id end_log_pos CRC32 0x221cda50 GTID last_committed= sequence_number= rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= '8ab82362-9c37-11e7-a858-000c29c1025c:251873'/*!*/;
# at
# :: server id end_log_pos CRC32 0x5df266e4 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
BEGIN
/*!*/;
# at
# :: server id end_log_pos CRC32 0xc1d41c5f Table_map: `replcrash`.`py_user_myisam` mapped to number
# at
# :: server id end_log_pos CRC32 0x27badc02 Write_rows: table id flags: STMT_END_F
### INSERT INTO `replcrash`.`py_user_myisam`
### SET
### @= /* INT meta=0 nullable=0 is_null=0 */
### @='7ATZSNFNIBW5DZNMNZYBMV' /* VARSTRING(96) meta=96 nullable=1 is_null=0 */
### @='2018-01-02 09:05:07' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### @='' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at
# :: server id end_log_pos CRC32 0x67285443 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
COMMIT
/*!*/;
# at
==================== mysqldump备份文件获取的binlog pos ====================
==================== 备份文件还原后,从库GTID_PURGED位置 ==================== # :: server id end_log_pos CRC32 0xf77ede80 GTID last_committed= sequence_number= rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= '8ab82362-9c37-11e7-a858-000c29c1025c:251874'/*!*/;
# at
# :: server id end_log_pos CRC32 0x506a2875 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
BEGIN
/*!*/;
# at
# :: server id end_log_pos CRC32 0x90b154e8 Table_map: `replcrash`.`py_user_innodb` mapped to number
# at
# :: server id end_log_pos CRC32 0x1d693238 Write_rows: table id flags: STMT_END_F
### INSERT INTO `replcrash`.`py_user_innodb`
### SET
### @= /* INT meta=0 nullable=0 is_null=0 */
### @='7ATZSNFNIBW5DZNMNZYBMV' /* VARSTRING(96) meta=96 nullable=1 is_null=0 */
### @='2018-01-02 09:05:07' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### @='' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at
# :: server id end_log_pos CRC32 0x87864022 Xid =
COMMIT/*!*/;
# at
==================== 启动复制后,py_user_innodb写入uid=331记录,成功 ==================== # :: server id end_log_pos CRC32 0xe492578a GTID last_committed= sequence_number= rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= '8ab82362-9c37-11e7-a858-000c29c1025c:251875'/*!*/;
# at
# :: server id end_log_pos CRC32 0xf08c4165 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
BEGIN
/*!*/;
# at
# :: server id end_log_pos CRC32 0xf16731d6 Table_map: `replcrash`.`py_user_myisam` mapped to number
# at
# :: server id end_log_pos CRC32 0x128aec5e Write_rows: table id flags: STMT_END_F
### INSERT INTO `replcrash`.`py_user_myisam`
### SET
### @= /* INT meta=0 nullable=0 is_null=0 */
### @='X1LME9HO5V7WXNOKBVZE' /* VARSTRING(96) meta=96 nullable=1 is_null=0 */
### @='2018-01-02 09:05:07' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### @='' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at
# :: server id end_log_pos CRC32 0x5cc8cc30 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
COMMIT
/*!*/;
# at
==================== 启动复制后,py_user_myisam写入uid=332记录,失败 ====================
==================== 从库py_user_myisam表已存在332记录,sql_thread停止 ==================== # :: server id end_log_pos CRC32 0xceb1ce4d GTID last_committed= sequence_number= rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= '8ab82362-9c37-11e7-a858-000c29c1025c:251876'/*!*/;
# at
# :: server id end_log_pos CRC32 0x38591b71 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
BEGIN
/*!*/;
# at
# :: server id end_log_pos CRC32 0xf80c2ae9 Table_map: `replcrash`.`py_user_innodb` mapped to number
# at
# :: server id end_log_pos CRC32 0x0bf4ae26 Write_rows: table id flags: STMT_END_F
### INSERT INTO `replcrash`.`py_user_innodb`
### SET
### @= /* INT meta=0 nullable=0 is_null=0 */
### @='X1LME9HO5V7WXNOKBVZE' /* VARSTRING(96) meta=96 nullable=1 is_null=0 */
### @='2018-01-02 09:05:07' /* DATETIME(0) meta=0 nullable=1 is_null=0 */
### @='' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at
# :: server id end_log_pos CRC32 0x1b75f9e0 Xid =
COMMIT/*!*/;
# at
...

二进志日志显示,按照py_user_myisam->py_user_innodb->py_user_myisam这样的顺序往表中写入数据。
使用备份文件搭建的从库,py_user_myisam表已包含UNLOCK TABLES之后的9条数据,但在备份文件中的@@GLOBAL.GTID_PURGED却是UNLOCK TABLES时刻的位置。因此在启动复制后,第一条操作py_user_innodb表成功,第二条操作py_user_myisam表失败,从库报主键冲突错误
那么应该如何修复这个错误呢?

# 删除从库py_user_myisam表大于等于冲突key的记录
mydba@192.168.85.132,3308 [replcrash]> delete from py_user_myisam where uid>=332;
# 重新启动sql_thread
mydba@192.168.85.132,3308 [replcrash]> start slave sql_thread;

总得来说就是只有innodb才会提供一致性备份!!!

1.2、DDL操作对备份的影响

建议先阅读后续章节,理解各备份过程后再返回阅读DDL操作对备份的影响
运行下面的脚本持续DDL操作

#!/user/bin/python
import string
import random
import MySQLdb
import time conn = MySQLdb.connect(host='192.168.85.132',
port=3306,
user='mydba',
passwd='mysql5719',
db='replcrash')
"""
create table py_user(
uid int not null auto_increment,
name varchar(32),
add_time datetime default current_timestamp,
server_id varchar(10),
primary key(uid),
key(name)
);
"""
counter = 1
while counter<=100:
addcol = 'col' + str(counter)
print addcol cursor = conn.cursor()
#DDL
cursor.execute("alter table py_user_innodb add %s int;" % addcol)
cursor.execute("alter table py_user_innodb drop column %s;" % addcol)
conn.commit()
counter += 1
time.sleep(0.0001)

Python DDL

逻辑备份数据库

# 清空general_log
[root@ZST1 logs]# cat /dev/null > /data/mysql/mysql3306/data/mysql-general.log # mysqldump
[root@ZST1 backup]# mysqldump -h127.0.0. -P3306 -uroot -p --single-transaction --master-data= replcrash >/data/backup/replcrash_dump_1323306_`date +%Y%m%d`.sql
Enter password:
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don not want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events.
mysqldump: Error : Table definition has changed, please retry transaction when dumping table `py_user_innodb` at row: # mysqlpump
[root@ZST1 backup]# mysqlpump -h127.0.0. -P3306 -uroot -p --single-transaction --add-drop-table --exclude-databases=mysql,sakila,backupdb -A >/data/backup/replcrash_pump_1323306_`date +%Y%m%d`.sql
Enter password:
mysqlpump: [ERROR] () Table definition has changed, please retry transaction
Dump process encountered error and will not continue.
Dump progress: / tables, / rows
[root@ZST1 backup]# # mydumper
[root@ZST1 mydumper]# mydumper -h 127.0.0.1 -P -u root -p mysql5719 --trx-consistency-only -v -t -o /data/backup/mydumper
..
** Message: Thread dumping data for `replcrash`.`py_user_innodb`
** Message: Thread dumping data for `replcrash`.`py_user_myisam`
** (mydumper:): CRITICAL **: Could not read data from replcrash.py_user_innodb: Table definition has changed, please retry transaction
** Message: Empty table replcrash.py_user_innodb
...

mydumper需要使用-v 3 显示详细信息,本身是不会报错的!!!如果想更容易再现错误,最好是备份的数据表较大、较多,适当降低并行线程数(-t),开启--trx-consistency-only,让其尽早解锁
生成的备份文件中,py_user_innodb表只有结构,没有数据
根据备份逻辑,在UNLOCK TABLES解除FTWRL到SELECT /*!40001 SQL_NO_CACHE */ * FROM `tbname`之间如果有DDL操作,就会造成上述错误
使用了with consistent snapshot子句开启一致性快照事务之后,如果一旦表结构定义发生改变,事务将无法对该表执行查询

使用WITH CONSISTENT SNAPSHOT子句,会话1显式开启一个事务之后先不执行查询,会话B使用DDL语句添加一个字段
会话1 会话2

修改隔离级别为RR
mydba@192.168.85.132,3306 [replcrash]> set tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)

修改隔离级别为RR
mydba@192.168.85.132,3306 [replcrash]> set tx_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)

显式开启一个事务,先不执行查询
mydba@192.168.85.132,3306 [replcrash]> start transaction with consistent snapshot;
Query OK, 0 rows affected (0.00 sec)

 
 

执行DDL语句添加字段,执行成功
mydba@192.168.85.132,3306 [replcrash]> alter table py_user_innodb add col1 int;
Query OK, 0 rows affected (0.13 sec)
Records: 0 Duplicates: 0 Warnings: 0

执行查询,报表定义已经改变的错误
mydba@192.168.85.132,3306 [replcrash]> select * from py_user_innodb;
ERROR 1412 (HY000): Table definition has changed, please retry transaction

 

物理备份数据库

[root@ZST1 backup]# innobackupex --defaults-file=/data/mysql/mysql3306/my.cnf -S /tmp/mysql3306.sock -uroot -pmysql5719 /data/backup/full/
:: [] Copying ./sakila/payment.ibd to /data/backup/full/--04_15--/sakila/payment.ibd
:: [] ...done
InnoDB: Last flushed lsn: load_index lsn
InnoDB: An optimized (without redo logging) DDLoperation has been performed. All modified pages may not have been flushed to the disk yet.
PXB will not be able take a consistent backup. Retry the backup operation
:: [] Copying ./replcrash/py_user.ibd to /data/backup/full/--04_15--/replcrash/py_user.ibd
:: [] ...done
:: [] Copying ./replcrash/py_user_innodb.ibd to /data/backup/full/--04_15--/replcrash/py_user_innodb.ibd
:: [] ...done

只要在备份期间(实际是备份InnoDB表期间,因为备份non-InnoDB表期间会加FTWRL只读锁,阻塞DDL、DML操作)执行DDL操作,innobackupex就会报错退出。原因就是DDL操作不会记录到redo log,PXB will not be able take a consistent backup.
因此备份期间要避免执行不记录事务日志的操作(ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE)

二、mysqlpump

2.1、备份过程

借助前面已开启general_log,来查看mysqlpump执行过程
MySQL 5.7.11起解决了--single-transaction和--default-parallelism的互斥问题

# 清空general_log
[root@ZST1 logs]# cat /dev/null > /data/mysql/mysql3306/data/mysql-general.log # 备份replcrash数据库,一致性备份(源码限制只有备份整个实例时才能返回GTID信息,因此这里使用-A,然后使用--exclude-databases排除不需要备份的db)
[root@ZST1 backup]# mysqlpump -h127.0.0. -P3306 -uroot -p --single-transaction --add-drop-table --exclude-databases=mysql,sakila,backupdb -A >/data/backup/replcrash_pump_1323306_`date +%Y%m%d`.sql
默认mysqlpump使用一个队列两个线程 [root@ZST1 data]# vim /data/mysql/mysql3306/data/mysql-general.log
...
Time Id Command Argument
--03T01::.623704Z Connect root@localhost on using TCP/IP
--03T01::.631266Z Query FLUSH TABLES WITH READ LOCK
--03T01::.667093Z Query SHOW WARNINGS
--03T01::.667310Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--03T01::.667520Z Query SHOW WARNINGS
--03T01::.667647Z Query START TRANSACTION WITH CONSISTENT SNAPSHOT
--03T01::.667792Z Query SHOW WARNINGS
--03T01::.679491Z Connect root@localhost on using TCP/IP
--03T01::.683019Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--03T01::.684865Z Query SHOW WARNINGS
--03T01::.685015Z Query START TRANSACTION WITH CONSISTENT SNAPSHOT
--03T01::.685114Z Query SHOW WARNINGS
--03T01::.686057Z Connect root@localhost on using TCP/IP
--03T01::.688856Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--03T01::.716231Z Query SHOW WARNINGS
--03T01::.716447Z Query START TRANSACTION WITH CONSISTENT SNAPSHOT
--03T01::.716558Z Query SHOW WARNINGS
--03T01::.716701Z Query UNLOCK TABLES
--03T01::.716857Z Query SHOW WARNINGS
...各种SHOW...
--03T01::.344380Z Query SHOW CREATE DATABASE IF NOT EXISTS `replcrash`
--03T01::.344468Z Query SHOW WARNINGS
--03T01::.344565Z Query SHOW TABLE STATUS FROM `replcrash`
--03T01::.380209Z Query SHOW WARNINGS
--03T01::.380416Z Query SHOW COLUMNS IN `py_user` FROM `replcrash`
--03T01::.381223Z Query SHOW WARNINGS
--03T01::.381408Z Query SHOW CREATE TABLE `replcrash`.`py_user`
--03T01::.381614Z Query SHOW WARNINGS
--03T01::.381950Z Query SHOW TRIGGERS FROM `replcrash` LIKE 'py_user'
--03T01::.382575Z Query SHOW WARNINGS
--03T01::.382764Z Query SHOW COLUMNS IN `py_user_innodb` FROM `replcrash`
--03T01::.383125Z Query SET SQL_QUOTE_SHOW_CREATE=
--03T01::.383334Z Query SHOW WARNINGS
--03T01::.383617Z Query SET TIME_ZONE='+00:00'
--03T01::.384037Z Query SHOW WARNINGS
--03T01::.385106Z Query SELECT `COLUMN_NAME`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS`WHERE TABLE_SCHEMA ='replcrash' AND TABLE_NAME ='py_user'
--03T01::.386099Z Query SHOW WARNINGS
--03T01::.386347Z Query SELECT SQL_NO_CACHE `uid`,`name`,`add_time`,`server_id` FROM `replcrash`.`py_user`
--03T01::.387102Z Query SHOW WARNINGS
--03T01::.387644Z Query SHOW WARNINGS
--03T01::.387997Z Query SHOW CREATE TABLE `replcrash`.`py_user_innodb`
--03T01::.388216Z Query SHOW WARNINGS
--03T01::.388487Z Query SHOW TRIGGERS FROM `replcrash` LIKE 'py_user_innodb'
--03T01::.389053Z Query SELECT `COLUMN_NAME`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS`WHERE TABLE_SCHEMA ='replcrash' AND TABLE_NAME ='py_user_innodb'
--03T01::.390054Z Query SHOW WARNINGS
--03T01::.390293Z Query SELECT SQL_NO_CACHE `uid`,`name`,`add_time`,`server_id` FROM `replcrash`.`py_user_innodb`
--03T01::.391566Z Query SHOW WARNINGS
--03T01::.391776Z Query SHOW COLUMNS IN `py_user_myisam` FROM `replcrash`
--03T01::.392559Z Query SHOW WARNINGS
--03T01::.392747Z Query SHOW CREATE TABLE `replcrash`.`py_user_myisam`
--03T01::.393065Z Query SHOW WARNINGS
--03T01::.393336Z Query SHOW TRIGGERS FROM `replcrash` LIKE 'py_user_myisam'
--03T01::.394146Z Query SHOW WARNINGS
--03T01::.394371Z Query SHOW FUNCTION STATUS WHERE db = 'replcrash'
--03T01::.396083Z Query SELECT `COLUMN_NAME`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS`WHERE TABLE_SCHEMA ='replcrash' AND TABLE_NAME ='py_user_myisam'
--03T01::.399053Z Query SHOW WARNINGS
--03T01::.399425Z Query SELECT SQL_NO_CACHE `uid`,`name`,`add_time`,`server_id` FROM `replcrash`.`py_user_myisam`
--03T01::.405719Z Query SHOW WARNINGS
--03T01::.405915Z Query SHOW PROCEDURE STATUS WHERE db = 'replcrash'
--03T01::.412340Z Query SHOW WARNINGS
--03T01::.414496Z Query SHOW WARNINGS
--03T01::.416755Z Query SHOW WARNINGS
--03T01::.417261Z Query SHOW EVENTS FROM `replcrash`
--03T01::.417884Z Query SHOW WARNINGS

即使备份一个db,general_log中也会出现很多其他库的内容(⊙_⊙)
mysqlpump备份过程(--single-transaction):
对于建立的第一个连接,执行FLUSH TABLES WITH READ LOCK,加上只读锁;对于其他连接(包含第一个连接),设置RR隔离级别,并开启一致性快照读START TRANSACTION WITH CONSISTENT SNAPSHOT;当所有连接(--default-parallelism设置多少个线程)都建立好后,再执行解锁UNLOCK TABLES;最后通过SELECT colname  FROM `tbname`备份数据
general_log中没有看到SHOW MASTER STATUS,猜测它类似于mydumper,也是在主线程FLUSH TABLES WITH READ LOCK后,就去获取GTID信息。
因此mysqlpump也会遇到在mysqldump中的坑
mysqlpump并行备份的部分参数需要在单线程模式才能应用,实际使用中建议先测试,对比输出结果分辨各参数的作用

2.2、--single-transaction

• --single-transaction
This option sets the transaction isolation mode to REPEATABLE READ and sends a START TRANSACTION SQL statement to the server before dumping data. It is useful only with transactional tables such as InnoDB, because then it dumps the consistent state of the database at the time when START TRANSACTION was issued without blocking any applications.
When using this option, you should keep in mind that only InnoDB tables are dumped in a consistent state. For example, any MyISAM or MEMORY tables dumped while using this option may still change state.
While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents and binary log coordinates), no other connection should use the following statements: ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE. A consistent read is not isolated from those statements, so use of them on a table to be dumped can cause the SELECT that is performed by mysqldump/mysqlpump to retrieve the table contents to obtain incorrect contents or fail.
• START TRANSACTION
The WITH CONSISTENT SNAPSHOT modifier starts a consistent read for storage engines that are capable of it. This applies only to InnoDB. The effect is the same as issuing a START TRANSACTION followed by a SELECT from any InnoDB table. 
The WITH CONSISTENT SNAPSHOT modifier does not change the current transaction isolation level, so it provides a consistent snapshot only if the current isolation level is one that permits a consistent read. The only isolation level that permits a consistent read is REPEATABLE READ.

该参数将事务隔离级别设置成Repeatable Read,并在dump之前发送start transaction语句给服务端。这只对事务表(比如innodb)很有用,因为在发出start transaction时,保证了在不阻塞任何应用下的一致性状态。对myisam和memory等非事务表,还是会改变状态的,当使用此参数的时候要确保没有其他连接在使用ALTER TABLE、CREATE TABLE、DROP TABLE、RENAME TABLE、TRUNCATE TABLE等语句,否则会出现不正确的内容或者失败。在mysql5.7.11之前,--default-parallelism大于1的时候和此参数互斥,必须使用--default-parallelism=0。5.7.11之后解决了--single-transaction和--default-parallelism的互斥问题

三、mydumper

3.1、备份过程

mydumper备份过程
1、连接目标数据库
2、通过show processlist来判断是否有长查询,根据参数long-query-guard和kill-long-queries决定退出或杀掉长查询
3、主线程flush tables with read lock;start transaction with consistent snapshot
4、主线程读取当前时间点的二进制日志文件名和日志写入的位置并记录在metadata文件中,以供即时点恢复使用
5、创建dump线程,缺省为4个
6、确定候选表,根据类别分别插入non_innodb_table、innodb_tables以及table_schemas链表
7、将候选表通过g_async_queue_push加入任务队列(队列最后元素是thread shutdown),由dump线程从队列中读取表信息并执行数据导出
8、备份完non_innodb_table后立即unlock tables解锁,以减少锁定时间
9、等待dump InnoDB tables完成

从备份逻辑中可以看出,mydumper需要在备份完非事务表之后才解锁,这就保证了事务表和非事务表的一致性备份。默认情况下,DML操作不会影响mydumper备份的一致性

3.2、--trx-consistency-only

这个参数退化为仅保证事务表的一致性备份,在备份非事务表前如果有数据写入就会导致数据与metadata不一致,有点类似前面的mysqldump、mysqlpump的味道
运行前面的PythonDML脚本,一直往py_user_myisam、py_user_innodb表中写入数据,测试--trx-consistency-only选项的效果

# 清空general_log
[root@ZST1 logs]# cat /dev/null > /data/mysql/mysql3306/data/mysql-general.log # 备份replcrash库(仅事务表一致性备份)
[root@ZST1 mydumper]# mydumper -h 127.0.0.1 -P -u root -p mysql5719 --trx-consistency-only -v -B replcrash -o /data/backup/mydumper
** (mydumper:): WARNING **: Using trx_consistency_only, binlog coordinates will not be accurate if you are writing to non transactional tables.
** Message: Connected to a MySQL server
** Message: Started dump at: -- :: ** Message: Written master status
** Message: Thread connected using MySQL connection ID
** Message: Thread connected using MySQL connection ID
** Message: Thread connected using MySQL connection ID
** Message: Thread connected using MySQL connection ID
** Message: Transactions started, unlocking tables
** Message: Thread dumping data for `replcrash`.`py_user`
** Message: Thread dumping data for `replcrash`.`py_user_innodb`
** Message: Thread dumping data for `replcrash`.`py_user_myisam`
** Message: Thread dumping schema for `replcrash`.`py_user`
** Message: Thread dumping schema for `replcrash`.`py_user_innodb`
** Message: Thread dumping schema for `replcrash`.`py_user_myisam`
** Message: Thread shutting down
** Message: Thread shutting down
** Message: Thread shutting down
** Message: Thread shutting down
** Message: Finished dump at: -- :: # 查看metadata
[root@ZST1 mydumper]# cat metadata
Started dump at: -- ::
SHOW MASTER STATUS:
Log: mysql-bin.
Pos:
GTID:8ab82362-9c37-11e7-a858-000c29c1025c:- Finished dump at: -- ::
[root@ZST1 mydumper]# # 还原replcrash库
[root@ZST1 mydumper]# myloader -h 127.0.0.1 -P -u root -p mysql5719 -o -B replcrash -d /data/backup/mydumper myloader不会产生binlog,也不会应用metadata中的GTID
# 设置GTID_PURGED
mydba@192.168.85.132, [replcrash]> reset master;
mydba@192.168.85.132, [replcrash]> SET @@GLOBAL.GTID_PURGED='8ab82362-9c37-11e7-a858-000c29c1025c:1-272303'; # 搭建复制
mydba@192.168.85.132, [replcrash]> change master to
master_host='192.168.85.132',
master_port=,
master_user='repl',
master_password='repl',
master_auto_position=; # 启动复制,查看复制状态
mydba@192.168.85.132, [replcrash]> start slave;
mydba@192.168.85.132, [replcrash]> show slave status\G
*************************** . row ***************************
Master_Log_File: mysql-bin.
Read_Master_Log_Pos:
Relay_Log_File: relay-bin.
Relay_Log_Pos:
Relay_Master_Log_File: mysql-bin.
Slave_IO_Running: Yes
Slave_SQL_Running: No
Exec_Master_Log_Pos:
Last_SQL_Errno:
Last_SQL_Error: Could not execute Write_rows event on table replcrash.py_user_myisam; Duplicate entry '' for key 'PRIMARY', Error_code: ; handler error HA_ERR_FOUND_DUPP_KEY; the event''s master log mysql-bin., end_log_pos
Retrieved_Gtid_Set: 8ab82362-9c37-11e7-a858-000c29c1025c:-
Executed_Gtid_Set: 8ab82362-9c37-11e7-a858-000c29c1025c:-
Auto_Position: # 大于等于冲突key的数据
mydba@192.168.85.132, [replcrash]> select * from replcrash.py_user_myisam where uid>=;
+-----+--------------------------------+---------------------+-----------+
| uid | name | add_time | server_id |
+-----+--------------------------------+---------------------+-----------+
| | MLGU22VB26RHNNYAY6IPPUJX9A74EM | -- :: | |
+-----+--------------------------------+---------------------+-----------+
row in set (0.06 sec) # mydumper产生的general-log
[root@ZST1 data]# vim /data/mysql/mysql3306/data/mysql-general.log
...
--04T01::.769877Z Query SET SESSION net_write_timeout =
--04T01::.770302Z Query SHOW PROCESSLIST
--04T01::.770886Z Query FLUSH TABLES WITH READ LOCK
--04T01::.771236Z Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
--04T01::.771430Z Query /*!40101 SET NAMES binary*/
--04T01::.772084Z Query SHOW MASTER STATUS
--04T01::.772331Z Query SHOW SLAVE STATUS
--04T01::.773386Z Query insert into py_user_myisam(name,add_time,server_id) values('MLGU22VB26RHNNYAY6IPPUJX9A74EM',now(),@@server_id)
--04T01::.773981Z Connect root@localhost on using TCP/IP
--04T01::.788273Z Query SET SESSION wait_timeout =
--04T01::.788874Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--04T01::.788972Z Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
--04T01::.789092Z Query /*!40103 SET TIME_ZONE='+00:00' */
--04T01::.789201Z Query /*!40101 SET NAMES binary*/
--04T01::.790091Z Connect root@localhost on using TCP/IP
--04T01::.790315Z Query SET SESSION wait_timeout =
--04T01::.791912Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--04T01::.792095Z Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
--04T01::.792307Z Query /*!40103 SET TIME_ZONE='+00:00' */
--04T01::.792418Z Query /*!40101 SET NAMES binary*/
--04T01::.793381Z Connect root@localhost on using TCP/IP
--04T01::.794631Z Query SET SESSION wait_timeout =
--04T01::.796301Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--04T01::.796404Z Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
--04T01::.796538Z Query /*!40103 SET TIME_ZONE='+00:00' */
--04T01::.796641Z Query /*!40101 SET NAMES binary*/
--04T01::.797414Z Connect root@localhost on using TCP/IP
--04T01::.798420Z Query SET SESSION wait_timeout =
--04T01::.799316Z Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
--04T01::.799425Z Query START TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
--04T01::.800345Z Query /*!40103 SET TIME_ZONE='+00:00' */
--04T01::.800449Z Query /*!40101 SET NAMES binary*/
--04T01::.800661Z Query UNLOCK TABLES /* trx-only */
--04T01::.801868Z Init DB replcrash
--04T01::.802332Z Query SHOW TABLE STATUS
--04T01::.804759Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `replcrash`.`py_user`
--04T01::.805137Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `replcrash`.`py_user_innodb`
--04T01::.807164Z Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `replcrash`.`py_user_myisam`
--04T01::.808786Z Query insert into py_user_innodb(name,add_time,server_id) values('MLGU22VB26RHNNYAY6IPPUJX9A74EM',now(),@@server_id)
--04T01::.809449Z Query SHOW CREATE DATABASE `replcrash`
--04T01::.810326Z Query SHOW CREATE TABLE `replcrash`.`py_user_innodb`
--04T01::.810638Z Query SHOW CREATE TABLE `replcrash`.`py_user`
--04T01::.811307Z Quit
--04T01::.811506Z Query SHOW CREATE TABLE `replcrash`.`py_user_myisam`
--04T01::.812272Z Quit
--04T01::.812512Z Query commit

48是python持续写入的线程、49是主线程、50~53是dump线程
所有连接建立后,主线程立即解锁UNLOCK TABLES /* trx-only */。主线程SHOW MASTER STATUS的后面紧接着python写入insert into py_user_myisam,实际这个写入操作是在主线程UNLOCK TABLES之后,dump线程备份py_user_myisam数据之前。这就导致备份的数据与metadata不一致,因此不推荐使用--trx-consistency-only选项

3.3、逻辑备份差异

mysqldump:只支持单线程工作,这就使得它无法迅速的备份数据
mysqlpump:并行的最小粒度是单个数据库对象,对于每张表的导出只能是单个线程的
mydumper:支持对单表多个线程备份,参数-r
多线程操作提升空间受限于磁盘的IO能力,在使用前做好磁盘IO的评估

四、XtraBackup

4.1、备份过程

innobackupex全备过程
1、start xtrabackup_log
2、copy .ibd、ibdata1
3、FLUSH TABLES WITH READ LOCK
4、copy .frm、.MYD、.MYI、misc files
5、SHOW MASTER STATUS
6、UNLOCK TABLES
7、stop and copy xtrabackup_log

备份开始时首先会开启一个后台检测进程,从当前checkpoint位置开始拷贝redo log,同时持续检测redo log,一旦发现redo中有新的日志写入,立刻将日志记入后台日志文件xtrabackup_log中。之后拷贝innodb的数据文件和系统表空间文件ibdata1,待拷贝结束后,执行flush tables with read lock操作,拷贝.frm,MYI,MYD,等文件,并且在这一时刻获得binlog的位置,最后会发出unlock tables,把表设置为可读可写状态,最终停止xtrabackup_log。
InnoDB表copy [.ibd、ibdata]+[redo log]借助InnoDB Crash Recovery机制保证一致性;non-InnoDB表使用FTWRL加只读锁后backup non-InnoDB tables and files。DML操作不会影响innobackupex备份的一致性

4.2、总结

  mysqldump mysqlpump mydumper innobackupex
FTWRL被阻塞 存在互斥锁,会被阻塞 存在互斥锁,会被阻塞 存在互斥锁,会被阻塞 存在互斥锁,会被阻塞
DDL操作导致备份异常 报错,表定义变更 报错,表定义变更 不报错,-v 3查看 报错,DDL操作没写redo log
DML操作影响数据一致性 non_InnoDB表不一致 non_InnoDB表不一致 默认一致,--trx-consistency-only会导致不一致 一致
其他       没有指定my.cnf导致备份一个错误的实例

对生产库的DDL操作、大事务、或者长时间锁表的操作,一定要避开备份时间(・ω・)

五、参考文档

mysqldump与innobackupex备份过程你知多少:http://www.cnblogs.com/xiaoboluo768/p/7560105.html
mysqlpump两个疑问点:http://www.fordba.com/mysqlpump_some_questions.html
MySQL 5.7 mysqlpump 备份工具说明:http://www.cnblogs.com/zhoujinyi/p/5684903.html
mysqlpump — A Database Backup Program:https://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html
mydumper:https://github.com/maxbube/mydumper
MySQL备份之【mydumper 学习】:http://www.cnblogs.com/zhoujinyi/p/3423641.html
mydumper备份数据库详解(已详细说明):https://yq.aliyun.com/articles/45741
mydumper备份原理和使用方法:http://www.cnblogs.com/linuxnote/p/3817698.html