闪回在MySQL中的实现和改进
如果无法正常显示,请先停止浏览器的去广告插件。
1. 闪回在MySQL中的实现和改进
唐洁
「3306π」福州站,2022.1.15
2. 目录
CONTENTS
01 MySQL闪回实现基础
02 数据库闪回能力现状
03 MySQL中DML闪回实现方案
04 MySQL中DDL闪回实现方案
3. 绝望的SQL
元芳,你怎么看
这个SQL?
4. 数据库闪回能力的业务价值
人祸
所为 • 沟通:IT流程的环节由不同的人员各司其职分工完成。文档?口头?
传递信息的缺失,沟通不畅导致
• 失误:DBA手滑写错/眼花看错,生而为人难以避免
• 工期:客户催老板急,开发人员赶工完成紧急任务,数据脚本未
进行充分测试
价值
意义 •
•
便捷:数据备份无需DBA专门操作,而是由数据库自动触发
补救:在DBA执行错误的数据提交操作之后,还能把数据恢复还原到
之前某个时刻的状态,最大程度的挽回损失
5. binlog文件功能
binlog文件用途
• mysql主服务器同步触发:同步二进制数据日志给从服务器:主服务器数据发生更新后,会把变动,以
event的形式,记录binlog文件,然后从服务器会拉取binlog文件解析。从服务器通过拉取并解析binlog
文件,实现数据的同步。
• 记录操作轨迹:binlog文件中记录了数据变更的信息。
• 数据恢复:借助binlog日志,可以恢复到故障之前的形态。
binlog文件更新方式
• Statement:文件中存的是sql语句,优点是传输的数据量比较少,缺点是很难保证主从一致。
• Row:文件中存的是更新的那一行的数据内容,优点是不会出错,缺点是传输的数据量比较大。
• Mixed:Statement和Row模式的结合。
6. 配置binlog
配置binlog文件
• 查看log_bin系统变量来判断当前MySQL服务器
是否生成binlog日志
启用binlog文件
• 重启服务器,设置log-bin启动选项:
--log-bin[=file_name]
例如:mysqld --log-bin=/user/greatdb/test
• log-bin启动选项也可以放在cnf配置文件
生成binlog文件
• 表示开启binlog,并将binlog写入MySQL服务
器的数据目录/user/greatdb/下,binlog日志文
• 上例中bin_log系统变量的值为ON,表明当前服务
器生成binlog,若为OFF表明当前服务器不生成
binlog。
件名就像是这样:
test.000001
test.000002
......
7. binlog文件格式
binlog文件的位置
• show variables like '%datadir%‘
• hexdump -C binlog.000006|more
输出
0xfe62696e(固定4个字节)
事件1(格式描述事件)
事件2
事件3
.
.
.
事件N
• 前面的4个字节fe 62 69 6e是魔数,标识文件类型
是binlog。
• 后面的二进制数据则表示事件详细数据。
binlog文件组成
事件头
事件体
8. binlog文件结构
主要事件类型
• FORMAT_DESCRIPTION_EVENT
• ANONYMOUS_GTID_LOG_EVENT/GTID_LOG_EVENT
• QUERY_EVENT
• TABLE_MAP_EVENT
• WRITE_ROWS_EVENT/UPDATE_ROWS_EVENT/DELETE_ROWS_EVENT
• XID_EVENT
事件组成
•
事件头+事件体
事件要素查看
• 客户端:SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
• 命令行:mysqlbinlog
9. 客户端方式查看binlog事件
mysql客户端执行SHOW BINLOG EVENTS,表示查看第1个binlog日志文件的内容。
主要列说明
• Log_name
• Pos
• Event_type
• Server_id
• End_log_pos
• Info
10. 命令行方式查看binlog事件
查看测试数据对应的binlog文件内容:
mysqlbinlog --base64-output=decode-rows -vv /home/percona/percona/release/data/binlog.000031
1
2
3
4
5
要
素
构
成
binlog中的最小事务单元的构成
• Anonymous_Gtid/Gtid
• Query
• Table_map
• Write_rows/Delete_rows/Update_rows
• Xid
11. 目录
CONTENTS
01 MySQL闪回实现基础
02 数据库闪回能力现状
03 MySQL中DML闪回实现方案
04 MySQL中DDL闪回实现方案
12. 竞品分析(1/4):oracle/ob
实现原理
• 基于回收站机制,把数据库改动前的镜像放到undo表空间中。
• 如果要回滚某个数据库对象, 只需要找到undo表空间中对应的undo数据即可。
优点
• 支持数据库级别(当误删除用户模式时适用)。
• 支持表级(drop/truncate命令删除的表适用)。
• 支持事务级闪回(对数据的增删改操作适用,只支持时间戳方式检索)。
缺点
• 闪回一般只适用于短时间内的数据恢复。
• 只能根据时间戳方式恢复。
事务级闪回操作步骤样例(SQL模式)
•
根据时间戳查询待闪回的历史记录:select * from 表名 as of timestamp to_timestamp('2021-08-04 11:00:00','yyyy-
mm-dd hh24:mi:ss');
•
数据回滚闪回: flashback table 表名 to timestamp to_timestamp('2021-08-04 11:00:00','yyyy-mm-dd hh24:mi:ss');
13. 竞品分析(2/4) :binlog2sql
实现原理
• 伪装成slave拉取binlog,从MySQL binlog解析出具体的SQL操作。
• 对其进行逆操作,最后在反向输出。
优点
•
简单python脚本,修改安装简单,支持增删改操作的回滚。
缺点
• mysql服务器必须开启,不支持离线模式。
• 不支持DDL语句,解析速度慢,效率低。
操作步骤样例(命令行模式)
•
生 成 闪 回 sql 脚 本 : binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -tuser --start-file='mysql-
bin.000054' --start-datetime='2021-08-01 11:00:00' --stop-datetime='2021-08-04 11:00:00' > rollback.sql
•
闪回脚本导入:mysql -h127.0.0.1 -P3306 -uadmin -p'admin' < rollback.sql
14. 竞品分析(3/4) :AliSQL数据库闪回
实现原理
• 基于MySQL,对于数据增删改的操作,mysql中的binlog日志以事件的形式,记录了数据操作的前后差异。
• 解析binlog中的事件,然后反序遍历,同时对增删改进行逆操作,最后输出对应数据回滚的binlog,将其导入mysql即
完成数据的闪回。
优点
•
在MySQL自带的mysqlbinlog命令中新增闪回参数-B,无需额外安装命令工具。
缺点
•
不支持DDL语句的回滚,升级困难。实现方式和MySQL内核代码紧密耦合,需要对mysql源码编译打补丁。
操作步骤样例(命令行模式)
•
生成闪回binlog文件:mysqlbinlog -B -v --start-position=8602 --stop-position=8783 /home/mysql/binlog.000013
> rollback.out
•
数据回滚闪回:mysqlbinlog rollback.out | mysql -u percona -ppercona -h127.0.0.1
15. 竞品分析(4/4) :TiDB闪回
实现原理
•
TIDB内部也实现了类似MySQL的binlog文件,因此实现原理同MySQL闪回模式。
优点
•
自带的drainer命令新增时间戳:-start-time、-end-time参数实现。
缺点
•
不支持DDL语句的回滚,只支持时间戳方式闪回。
操作步骤样例(命令行模式)
•
生 成 闪 回 binlog 文 件 : 输 入 drainer -pd-urls https://127.0.0.1:2379 -dest-type flashback -start-time "209-12-25
00:00:00" -end-time "2019-12-25 10:00:00",生成闪回的binlog文件
•
数据回滚闪回:reparo -data-dir binlog文件目录
16. 目录
CONTENTS
01 MySQL闪回实现基础
02 数据库闪回能力现状
03 MySQL中DML闪回实现方案
04 MySQL中DDL闪回实现方案
17. DML闪回实现方案
实现原理
•
基于binlog的实现方式:解析并处理binlog文件中的事件,然后反序遍历,同时对增删改进行反转逆操作。
实现功能
• 新增闪回命令flashback方式实现。
• 支持DML语句闪回。
操作步骤样例(命令行模式)
•
生成闪回binlog文件:
flashback --start-position=8602
--stop-position=8783
--binlogFileNames=/home/mysql/binlog.000013 > rollback.out
•
数据回滚闪回:
mysqlbinlog rollback.out | mysql -u percona -ppercona
18. MySQL字段长度限制的计算方法
packlen:一种可变长的存储数值的协议
• 如果第一个字节数值小于0xfb(251),则该数值通过1个字节存储;
• 如果第一个字节数值等于0xfc(252),则该数值通过2个字节存储;
• 如果第一个字节数值等于0xfd(253),则该数值通过3个字节存储;
• 如果第一个字节数值等于0xfe(254),则该数值通过8个字节存储;
packlen的优点
• 读取第一个字节,根据第一个字节的值,来获取数据真正有多少个字节。
• 节约存储空间。
19. 闪回binlog事件解析过程(1/3)
TABLE_MAP_EVENT事件结构
建表语句:
create table key.a(
id int(2) not null,
name varchar(253) null
);
fixed
036B657900
variable
length
20. 闪回binlog事件解析过程(2/3)
WRITE_ROWS_EVENT事件头结构
timestamp 4byte
event_type 1byte
event
header
service_id 4byte
event_length 4byte
next event pos 4byte
flag 2byte
event
body
event content XX byte
crc 4byte
21. 闪回binlog事件解析过程(3/3)
WRITE_ROWS_EVENT事件体结构
table_id 6byte
fixed
flag1 2byte
flag2 2byte
packlen column num ->c_num
variable
length
(c_num+7)/8 column is use
(c_num+7)/8 column is null
data
数据内容说明:
varchar length
22. DML闪回实现步骤
数据解析 事件识别
• 基于row模式的binlog文件,先解析出SQL增删 • FORMAT_DESCRIPTION_EVENT
改的操作轨迹。
• TABLE_MAP_EVENT
• 闪回日志格式必须是binlog_format=row,
• ROWS_EVENT
binlog_row_image=full。
• QUERY_EVENT
• XID_EVENT
操作反转 顺序反转
• 插入映射成删除 • 操作顺序逆序遍历处理
• 删除映射成插入
• 更新交换新旧数据区间
输出
数据回滚binlog文件
23. 目录
CONTENTS
01 MySQL闪回实现基础
02 数据库闪回能力现状
03 MySQL中DML闪回实现方案
04 MySQL中DDL闪回实现方案
24. DDL闪回的实现方案
挑战
删表操作是危险的行为,而目前主流的MySQL闪回能力主要集中在针对DML语句的回滚还原,对于DDL语句的回滚
面临的挑战:
• 文件格式binlog_format=row对于DDL语句的局限性。
• 删表操作在binlog只记录一个sql statement。
思路
•
检测drop table语句转换成先delete再删表
•
•
性能考量:记录多时,处理性能低。
引入表回收站机制
• 新建备份#bak_database:用于保存被删除的历史数据。
• 监听删表事件:在删除的动作开始之前,把表数据备份起来,然后留一个空表,在空表上执行“删除”操作。
25. 表回收站实现流程
MySQL删表流程(基于8.0.25)
创建线程接收用户请求
handle_connection(connection_handler_per_thread.cc)
do_command(sql_parse.cc)
dispatch_command(sql_parse.cc)
dispatch_sql_command(sql_parse.cc)
mysql_execute_command(sql_parse.cc)
识别删表sql_command事件:SQLCOM_DROP_TABLE
实现逻辑
• 生成备份表名:原表+时间戳+uuid/随机数
• 构造备份表标识:Table_ident(const LEX_CSTRING &db_arg, const LEX_CSTRING &table_arg)
• 备份表加载至Query_block:add_table_to_list
• 权限校验:当前用户是否有drop表权限
• 当前表移至备份表:rename `current_tbl` into `#bak_database`.`current_tbl_xxxxx`
26. 表回收站实现效果
recycle
schema
recycle schema定义
•
初始化时机:MySQL数据库启动的时候,初始化一个专用回收站的schema,命名为 "table_recycle",作为回收
站专有database。
•
权限控制:recycle_bin作为回收站的schema,定义为系统级database,用户没有权限做修改和删除。
27. 谢 谢 聆 听
THANKS FOR YOUR ATTENTION