山竹来临,窝在家里整理个人文档。1 innobackupex --defaults-file=/apps/conf/mysql/mysql5_3306.cnf --socket=/tmp/mysql3306.sock --user=[*]--password=[*] --no-timestamp /apps/mysql_backup/test_backup_1 > /apps/mysql_backup/backup.log 2>&1
xtrabackup: The latest check point (for incremental): '1209962' xtrabackup: Stopping log copying thread. .xtrabackup: warning: Log block checksum mismatch (block no 2364 at lsn 1209856): expected 1161267116, calculated checksum 1312610971 xtrabackup: warning: this is possible when the log block has not been fully written by the server, will retry later. 180912 15:30:11 >> log scanned up to (1209856) 180912 15:30:11 Executing UNLOCK TABLES 180912 15:30:11 All tables unlocked 180912 15:30:11 Backup created in directory '/apps/mysql_backup/test_backup_1/' MySQL binlog position: filename 'mysql-bin.000001', position '26708128' 180912 15:30:11 [00] Writing /apps/mysql_backup/test_backup_1/backup-my.cnf 180912 15:30:11 [00] ...done 180912 15:30:11 [00] Writing /apps/mysql_backup/test_backup_1/xtrabackup_info 180912 15:30:11 [00] ...done xtrabackup: Transaction log of lsn (1209962) to (1209856) was copied. xtrabackup: error: last checkpoint LSN (1209962) is larger than last copied LSN (1209856).
数据库实例运行正常的情况,在各个log buffer中,会存有 各个LSN,可以通过 show engine innodb status 查看,但是注意,这个lsn并非是直接从磁盘文件获取,而是从buffer 中获取。说明如下:
dba@localhost : (none) 17:00:21> show engine innodb status \G ...... --- LOG --- Log sequence number 4158179984 Log flushed up to 4158179984 Pages flushed up to 4158179984 Last checkpoint at 4158179975 0 pending log flushes, 0 pending chkp writes 128445 log i/o's done, 0.00 log i/o's/second ...... # Log sequence number: 当前系统最大的LSN号 # log flushed up to: 当前已经写入redo日志文件的LSN # pages flushed up to:已经将更改写入脏页的lsn号 # Last checkpoint at:系统最后一次刷新buffer pool脏中页数据到磁盘的checkpoint # LSN1 = Log sequence number# LSN2 = log flushed up to# LSN3 = pages flushed up to# LSN4 = Last checkpoint at# LSN1 >= LSN2 >= LSN3 >= LSN4
2 备份错误解读
说明xtrabckup 同步 redo log 到完成的时候,自身的 redo log 最后的 lsn 跟 当前数据库的 ib_logfile文件最后的 lsn对比,发现不匹配。

发现 ib_logfile[*]文件确实被覆盖。

3 排查问题
哇,原来 文件被删除,这里有几个疑问 :
- 为何文件被删除,不影响3306 实例 mysqld 的运行,3306 仍支持正常的 dml及ddl操作?
- 306的redo log 是写入到哪些地方?
- 3306实例丢失的文件能否恢复,能否正常使用?
- 为何 只有 redo log 文件被删除,是什么操作导致?
3.1 文件被删,实例为何能正常运行
- i_count:文件使用者或者被调用的数量,理解为内存引用的计数器。文件被进程打开使用的时候,自增+1。
- i_nlink:硬链接的数量,理解为磁盘引用计数器。创建文件的硬链接的时候,自增+1。
那么被进程调用的文件,遭遇 rm 操作,那么它将何去何从呢?
测试1:在运行的新实例 3006 上,删除3个文件后检查

3.2 数据实际写入到哪里,原被覆盖文件?proc文件系统文件?
测试2:删除表格文件,查看句柄size是否变化?
测试内容:删除ib_logfile0文件及tbb.ibd文件,往 tbb 表格插入数据,查看 ib_logfile0大小及tbb.ibd大小
测试过程:见截图
测试结果:因为ib_logfile 是固定大小1G,无法查看到change时间,故不能验证;但是可以从 tbb.ibd 文件大小得知,实际是 redo log 是写入到 被删除的文件的。

3.3 恢复被删除实例数据文件
- 若是主库文件被删
- 检查从库是否正常、是否无删除文件
- 从库正常
- 方案1
- 主从切换
- 旧主上,根据deleted句柄重定向被删除的数据块到原先的磁盘位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 方案 2
- 重做 旧主库,重做后恢复从库使用
- 方案1
- 从库不正常,文件也被删
- 从库,停止复制
- 从库,根据deleted句柄重定向被删除的数据块到原先的磁盘位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 从库,恢复复制
- 检查从库追上主库
- 主从切换
- 旧主新从,停止复制,重定向文件内容 或者重做 从库
- 从库正常
- 检查从库是否正常、是否无删除文件
- 若是从库文件被删
- 方案1
- 从库停止复制
- 从库上,根据deleted句柄重定向被删除的数据块到原先的磁盘位置,例: cat /proc/16979/fd/36 > /apps/dbdat/mysql5_data3306/sophia/tba.ibd
- 方案2
- 重做 旧主库,重做后恢复从库使用
- 方案1
3.4 为何仅ib_logfile[*]文件被删除,为何被删
180912 15:09:51 [Note] Plugin 'FEDERATED' is disabled. 180912 15:09:51 InnoDB: The InnoDB memory heap is disabled 180912 15:09:51 InnoDB: Mutexes and rw_locks use GCC atomic builtins 180912 15:09:51 InnoDB: Compressed tables use zlib 1.2.3 180912 15:09:51 InnoDB: Using Linux native AIO 180912 15:09:51 InnoDB: Initializing buffer pool, size = 1.0G 180912 15:09:51 InnoDB: Completed initialization of buffer pool InnoDB: The first specified data file /apps/dbdat/mysql5_data3306/ibdata1 did not exist: InnoDB: a new database to be created! 180912 15:09:51 InnoDB: Setting file /apps/dbdat/mysql5_data3306/ibdata1 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:09:55 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile0 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile0 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:09:58 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile1 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile1 size to 1000 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 180912 15:10:01 InnoDB: Log file /apps/dbdat/mysql5_data3306/ib_logfile2 did not exist: new to be created InnoDB: Setting log file /apps/dbdat/mysql5_data3306/ib_logfile2 size to 1000 MB
为何使用命令指定参数执行新建实例,会覆盖其他实例的的文件呢?
为何使用 命令执行新建实例,会覆盖其他实例的的文件呢?
| File Name | Purpose |
| /etc/my.cnf | m |
| /etc/mysql/my.cnf | Global options |
| SYSCONFDIR/my.cnf | Global options |
| $MYSQL_HOME/my.cnf | Server-specific options (server only) |
| defaults-extra-file | The file specified with --defaults-extra-file, if any |
| ~/.my.cnf | User-specific options |
| ~/.mylogin.cnf | User-specific login path options (clients only) |
--basedir=--innodb_log_group_home_dir--log-error=/apps/logs/mysql/error3307.log
并不,当存在默认路径的配置文件时,除了指定参数外,还是会去读 默认路径 上的配置文件 为主。
TIPS:
mysqld: [Warning] World-writable config file '/etc/my.cnf' is ignored.
4 错误原因总结
innodb_log_group_home_dir 指向了 3306 实例,覆盖了 3306 实例的 ib_logfile[*] 文件。
这是因为 3307 实例初始化的过程中,读取 /etc/my.cnf 配置文件的时候,5.7版本已经没有innodb_additional_mem_pool_size参数,故初始化到这里的时候,报错
2018-09-12T07:26:06.003983Z 0 [ERROR] unknown variable 'innodb_additional_mem_pool_size=32m'
2018-09-12T07:26:06.004004Z 0 [ERROR] Aborting
2018-09-12T07:26:06.004192Z 0 [Note] Binlog end
2018-09-12T07:26:06.010705Z 0 [Note] InnoDB: FTS optimize thread exiting.
2018-09-12T07:26:06.010917Z 0 [Note] InnoDB: Starting shutdown...
2018-09-12T07:26:06.111107Z 0 [Note] InnoDB: Dumping buffer pool(s) to /apps/dbdat/mysql57_data3307/ib_buffer_pool
2018-09-12T07:26:06.111312Z 0 [Note] InnoDB: Buffer pool(s) dump completed at 180912 15:26:06
2018-09-12T07:26:07.849696Z 0 [Note] InnoDB: Shutdown completed; log sequence number 1209962
2018-09-12T07:26:07.849933Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
- 初始化 5.7版本的3306实例,生成一张大表
- 拷贝 5.7 3306 实例的配置文件到 /etc/my.cnf
- 指定参数初始化 3307实例
- 确认 3306 实例的 ib_logfile 被覆盖,但 3306 实例可以正常执行操作
- 备份 3306 实例正常,执行备份期间无错误
- 备份 3306实例期间,等待其拷贝完某张空表 tb.ibd 文件后,迅速 insert 这张表 5000 行数据
- 进行还原操作,验证备份是否有效
- 检查 tb.ibd 文件大小 为几十kb
- 检查 备份文件夹中的 xtrabackup_logfile , 该文件仅为 2.5k,并未记录 insert tb.ibd文件的操作
- apply log 后启动文件,发现tb.ibd 仍然为空表
- 结论
- 同版本覆盖的情况下
- 因为在做数据操作的时候,ib_logfile 没有变动,故xtrabackup_logfile 文件,并没有记录到实际的redo log,所以其 xtrabackup_binlog_info 记录的log 跟pos 与实际不相符
5 处理流程总结
- 备份失败
- 失败原因:ib_logfile被覆盖
- 引发问题
- 运行中的db实例,文件被覆盖,为何可正常运行?
- linux 删除文件原理,rm 被进程使用的文件,仅删除 i_nlink,未删除实际数据块,可从proc文件系统查找
- 当文件被覆盖后,还会继续写入 进程的修改数据吗?
- 写入到 proc 指向的数据块中,正常读写
- 如何恢复被覆盖的文件?
- 确保无数据写入proc 指向的 deleted文件,cat 重定向(注意耗时)
- 运行中的db实例,文件被覆盖,为何可正常运行?
- 查找文件被覆盖的原因
- 引发问题
- 为何只有 ib_logfile[*]被覆盖?
- 初始化仅指定部分参数,指定参数优先级别最高,其他读取默认配置文件参数,因为指定了 innodb-data-file-path、datadir,没有指定 innodb_log_group_home_dir,故仅覆盖 ib_logfile[*]
- mysql初始化 指定参数 跟 默认路径配置文件的优先级 ?
- 优先级别高低
- 用户指定参数
- 默认路径配置文件参数,按照默认路径排序,属性是 global 的,靠前的优先级别底,越后越高
- mysqld 默认参数值
- 优先级别高低
- 为何某些情况下配置了/etc/my.cnf,但是不读取?
- 当 配置文件的权限为所有人可写的情况下,mysql担心该配置文件被恶意修改,故会忽略该文件,不读该文件配置
- mysqld: [Warning] World-writable config file '/etc/my.cnf' is ignored.
- 注意查看 配置文件权限 不是 777 权限
- 为何只有 ib_logfile[*]被覆盖?
- 引发问题
6 思考与改进
关于部署,使用defaults-file指定部署
关于恢复,注意主从处理及readonly 处理,确保cat 重定向的过程中,proc文件系统被删除的文件无写入
关于监控,线上应当添加对相关data目录的 proc deleted句柄的相关监控