开启binlog
这是一个mysql配置文件示例
# 开启二进制日志
log-bin = mysql-bin
# 日志格式(mixed, statement, row)
binlog_format = mixed
# 设置过期时间
expire_logs_days = 30
# server id必须唯一
server-id = 1
查看日志命令
-- 列出二进制日志
show master logs;
-- 具体查看某个日志事件
show binlog events in 'mysql-bin.000003'
show binglog events
show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
选项解析:
IN ‘log_name’ 指定要查询的binlog文件名(不指定就是第一个binlog文件)
FROM pos 指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)
LIMIT [offset,] 偏移量(不指定就是0)
row_count 查询总条数(不指定就是所有行)
启动一个测试用的Docker
docker run --name test-mysql -d \
-v /home/fayfox/mysql/conf:/etc/mysql/mysql.conf.d/:ro \
-v /home/fayfox/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql
模拟数据
构建测试库
-- 建库
create database binlogtest;
-- 使用库
use binlogtest;
-- 建表
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL DEFAULT '',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 初始测试数据
INSERT INTO `test`(`title`) VALUES ('a'), ('b'), ('c');
备份库
mysqldump -uroot -p -F binlogtest > ./bak.sql
-F 会在备份前先flush logs
编辑数据
UPDATE `test` SET `title` = 'dd' WHERE `id` = 3;
INSERT INTO `test`(`title`) VALUES ('e');
删表(模拟异常操作)
DROP TABLE `test`;
进行恢复
刷新日志索引
flush logs;
避免当前日志文件继续写入,使问题复杂化
导入之前的备份
利用mysql命令导入
mysql -uroot -p -D binlogtest < bak.sql
进入mysql客户端后用source命令导入
source /var/lib/mysql/bak.sql
查找问题语句位置
利用show binlog events查看
show binlog events in 'binlog.000003';
+---------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
| binlog.000003 | 696 | Write_rows | 1 | 743 | table_id: 66 flags: STMT_END_F |
| binlog.000003 | 743 | Xid | 1 | 774 | COMMIT /* xid=76 */ |
| binlog.000003 | 774 | Anonymous_Gtid | 1 | 847 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000003 | 847 | Query | 1 | 988 | use `binlogtest`; DROP TABLE `test` /* generated by server */ /* xid=78 */ |
| binlog.000003 | 988 | Rotate | 1 | 1032 | binlog.000004;pos=4 |
+---------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------+
15 rows in set (0.00 sec)
可以看到,DROP语句从847位置开始
利用mysqlbinlog命令查看
mysqlbinlog binlog.000003
# at 774
#180717 14:59:38 server id 1 end_log_pos 847 CRC32 0x9fbb510b Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=no original_committed_timestamp=1531839578681339 immediate_commit_timestamp=1531839578681339 transaction_length=214
# original_commit_timestamp=1531839578681339 (2018-07-17 14:59:38.681339 UTC)
# immediate_commit_timestamp=1531839578681339 (2018-07-17 14:59:38.681339 UTC)
/*!80001 SET @@session.original_commit_timestamp=1531839578681339*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 847
#180717 14:59:38 server id 1 end_log_pos 988 CRC32 0x60ea3242 Query thread_id=8 exec_time=0 error_code=0 Xid = 78
use `binlogtest`/*!*/;
SET TIMESTAMP=1531839578/*!*/;
DROP TABLE `test` /* generated by server */
/*!*/;
同样可以看到,DROP语句从847位置开始
执行恢复
mysqlbinlog --stop-position=847 ./binlog.000003 | mysql -uroot -p -D binlogtest