暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MySQL binlog专题

binlog基本概念

binlog是一个二进制格式的文件,用于记录用户对数据库更新的SQL语句信息(DDL,DCL,DML),不记录查询语句(select、show这类的操作)。

binlog特点

  • 1.binlog是在MySQL的server层实现的,是所有存储引擎共用的;
  • 2.binlog是逻辑日志,,记录的是一条SQL语句的原始逻辑;
  • 3.binlog是追加写入的,不会覆盖之前的日志。

binlog使用场景

  • 1.主从复制:详见主从复制篇;
  • 2.数据恢复:除了redolog在数据库崩溃后恢复时会用xid向binlog确认事务完整性以外,还有通过mysqlbinlog工具来进行数据恢复的场景。经常使用的第三方工具reverse_sql也是通过binlog解析出回滚用的反向SQL。

binlog记录内容和模式

SQL语句记录内容

  • DDL:原封不动的记录当前DDL(statement语句方式)
  • DCL:原封不动的记录当前DCL(statement语句方式)
  • DML:只记录已经提交的事务DML(insert update delete)

DML记录模式
记录模式由binlog_format(binlog的记录格式)参数影响
statement(5.6默认)SBR(statement based replication):语句模式原封不动地记录当前DML
ROW(5.7默认)RBR(ROW based replication):记录实际开机的变化,用户看不懂,需要工具分析

  • mixed(混合)MBR(mixed based replication):混合模式,一般情况用statement模式,对于statement无法复制的用ROW模式,一般不用混合模式。
  • statement:优点是可读性较高,日志量少,减少io。但缺点是不够严谨,记录仅是每条修改数据的SQL(如果是批量修改,则记录的不是单条SQL,而是批量修改SQL语句的事件),在使用一些函数时会导致主从不一致。
  • ROW:缺点是可读性很低,日志量大,但足够严禁,记录的是行变化。生产环境我们希望数据最大化的一致,因此建议使用ROW模式。
    row模式优点是能清楚记录每一行数据修改细节,能完全实现(包括存储过程及触发器)主从数据同步和数据恢复。我们很多基于binlog的工具都要求必须采用ROW模式。

binlog写入流程

binlog文件结构
主要是log event,不同的修改操作对应不同的log event。
比较常见的log event有:query event,ROW event,XID event等等。
文件结构参考下图:

图片.png

binlog落盘策略
binlog写入顺序:binlog cache(write) → OS cache → fsync()写入磁盘
binlog刷数据到磁盘是由一个参数控制的:sync_binlog

show variables like '%sync_binlog%';
  • sync_binlog = 0:每次提交事务都只write,不fsync,不建议设置为0,丢失的数据不可控。
  • sync_binlog = 1:每次提交事务都fsync,生产环境若要保证最高安全性则设为1。
  • sync_binlog = n(n>1):每次提交事务都write,但积累n个事务才fsync到磁盘,一般设为100~1000中某个值,在崩溃时最多丢失n个事务,丢失量可控。

binlog写入流程描述
参考下图:

图片.png

1.根据操作和记录模式触发event事件,生成log event;
2.事务执行过程中,先把日志写到binlog cache,每个事务都会被分配一个binlog cache内存空间。事务提交的时候,再把日志写到binlog文件当中。binlog文件是只有一份的,共用的。
3.事务提交,执行器会把binlog cache里的完整事务写入binlog文件,然后执行器会清空binlog cache。

配置和查看binlog

启用binlog
向配置文件my.cnf增加几个基本参数:

binlog_format=row
log_bin=/binlog/mysqlbin
log_bin_index=/binlog/mysql-bin.index

重启后生效。(8.0默认开启,且保存在数据目录下)
检查是否生效:

show variables like '%log_bin%';

这里补充常用的binlog和复制参数:

# 二进制日志文件的缓存大小
binlog_cache_size = 131072
# 验证binlog的完整性,默认CRC32,此处禁用校验
binlog_checksum=NONE    
# 二进制日志文件过期时间,两参数配置一个即可
binlog_expire_logs_seconds=172800
expire_logs_days = 3
# 记录每一行数据被修改的形式
binlog_format=row
# 二进制日志记录的行数据格式
# binlog_row_image='minimal' 
# 开启记录详细的行操作信息
binlog_rows_query_log_events =1
# 开启记录详细的行操作信息
enforce_gtid_consistency=ON
# 启用GTID
gtid_mode=ON
# 启用binlog的开关,并指定binlog名称。
log_bin=/binlog/mysqlbin
# 指定二进制日志的索引文件名称。
log_bin_index=/binlog/mysql-bin.index
# 从服务器上记录二进制日志的方式,记录所有从服务器的更新操作到主服务器,默认关闭
log_slave_updates=OFF
# 二进制日志中主服务器的相关信息存储位置,将主服务器的二进制日志信息存储在MySQL的数据表中。
master_info_repository=TABLE
# 只读,一般从节点会配置,MGR不用主动配置
read_only=1
# 设定从服务器的中继日志中的相关信息存储位置,将中继日志信息存储在MySQL的数据表中
relay_log_info_repository=TABLE
# 部分复制的参数
replicate-do-db=需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可
replicate-ignore-db=需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可
# 实例启动时不自动启动复制线程
skip_slave_start
# 指定从服务器在进行并行复制时的行为,使用逻辑时钟进行并行复制。这意味着从服务器会根据主服务器上的时间戳来执行复制操作,而不是物理时间。
slave_paralle_type=LOGICAL_CLOCK
# 从服务器在进行并行复制时使用的线程数
slave_paralle_workers=4
# 主从复制过程中从服务器可以自动跳过的错误号
slave_skip_errors = 1032,1062,1053,1146
# 每个事务提交时将二进制日志同步到磁盘
sync_binlog=1

使用SQL命令查看binlog
查看binlog文件列表:

show binary logs;

查看正在写入的binlog

show master status;

查看binlog文件信息

show binlog events;

其中
Log_name是当前事件所在binlog名称,
Pos是当前事件起始位置,即起始position号,
Event_type是事件类型,如Query、Table_map、Update_rows、Xid等等…
Server_id,
End_log_pos是当前事件结束位置,用End_log_pos减去Pos则是占用字节数,
Info是具体信息。

查看指定文件内容

show binlog events in 'mysqlbinlog.000001'\G

或使用mysqlbinlog命令来查看,专门用于查看binlog的工具。一般需要导出到文件。

mysqlbinlog mysqlbinlog.000001
mysqlbinlog mysql-bin.000002 >/tmp/a.sql 

binlog与redolog

1.redolog是innodb特有的。而binlog是MySQL server层实现的,因此所有引擎都能使用。
2.redolog是物理日志,记录的是xxx表空间xx页在xxx偏移量做了什么修改,值是多少,记录内容相对较少。而binlog是逻辑日志,记录SQL语句相关信息。
3.redolog是循环写入,空间一定是会被用完的,会产生覆盖,需要write pos和checkpoint搭配使用。binlog是追加写,写到一定大小会切换到下一个日志文件,但不会覆盖之前的,日志是全量保存的。
4.redolog作为服务器异常宕机后事务数据自动恢复时使用,具备crash-safe能力(所有已提交事务在mysql宕机重启后仍然存在,所有没提交的事务数据自动回滚)。binlog可以在主从复制和数据恢复使用,但不具备crash-safe能力。

为什么崩溃恢复不使用binlog?
1.恢复机制:mysql可以根据redo日志中的各种信息,来确定恢复的起点和终点,redo是以哈希表的方式记录的。
2.binlog恢复:binlog主要用于人工恢复数据,redolog是对用户不可读的,是mysql自己使用的,用于保证在数据库崩溃时的事务持久性。当数据库崩溃后,想要恢复未刷盘但已经写入redo log和binlog的数据到内存时,binlog是无法恢复的,虽然binlog拥有全量的数据,但是没有一个标识让innodb判断哪些数据已经写入表(写入磁盘表空间),哪些数据还没写入。
比如,binlog记录了两条日志
- 记录1:给id=2这一行的c字段+1
- 记录2:给id=2这一行的c字段+1
在记录1入表之后,记录2还没有入表时,数据库挂了。重启后,如果只是通过binlog无法判断两条记录哪条写入磁盘了,哪条没写,不管是两条都恢复至内存还是都不恢复,都不对。
但如果有了redolog,只要刷入磁盘的数据都会从redolog抹除掉。数据库重启之后,直接把redolog中的数据都恢复到内存就可以了。

常用的binlog维护操作

日志滚动:
show binary logs; 查看binlog文件
flush logs; 手动触发滚动日志
或在linux命令行下

mysqladmin -uroot -p123 flush-logs 

也触发滚动日志
binlog大小限制,默认为1个G,达到此值后会自动滚动

select @@max_binlog_size;  

mysqldump -F 也会自动滚动
重启mysql也会自动滚动
日志删除:
谨记:不要使用rm命令删除,因为不是数据库行为,会造成一些异常
①自动删除:
select @@expire_logs_days; 默认是0,单位是天,代表永不删除
阈值设置多少天合适?
一般是设置刚好超过一个全备周期:7+1天,空间够的话生产数据库建议2个全备+1天
②手动删除

purge binary logs to 'mysql-bin.000006';  

删除到6为止,实际删1至5

reset master; 

全清空,编号也从1开始,此操作主从必宕,需要修复

获取binlog文件列表:
show binary logs;

基于时间点截取,以及查看具体sql内容参考文章:

https://blog.csdn.net/qq_44697035/article/details/102583859

mysqlbinlog --base64-output=decode-rows -v  --start-datetime="2021-11-15 9:00:00" --stop-datetime="2021-11-15 9:50:00" /binlog/mysqlbin.000095 |more > /tmp/both118.sql

例2

mysqlbinlog --verbose --base64-output=decode-rows -vv --database=your_database_name binlog-file-name

还可以对其进行进一步过滤,比如:

grep -B0 -A27 -w 'DELETE FROM `kdb`.`t_diag_reportinfo`' mydiag.sql >diagreportinfo.sql 

B即before,A即after,意思是取目标行前后多少行

在vim中过滤并打印到文件:

: 2, 200 w ./data_copy.csv
最后修改时间:2025-02-17 14:56:17
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论