MySQL-binlog
参考文献
- MySQL技术内幕 InnoDB存储引擎
- MySQL 8 Cookbook
binlog
什么是binlog
?
- 二进制日志包含数据库的所有更改记录,包括数据和结构两方面.二进制不记录
SELECT
或SHOW
等不修改数据的操作. - 运行带有二进制日志的服务器会带来轻微的性能影响.二进制日志能保证数据库出现故障时数据是安全的.
- 只有完整的事件或事务才会被记录或者回读.
binlog
格式
-
该参数可设的值有
STATEMENT
,ROW
,MIXED
. -
STATEMENT
模式下,每一条会修改数据的sql都会记录在binlog
中.不需要记录每一行的变化,减少了binlog
日志量,节约了IO,提高性能.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制. -
ROW
格式,二进制日志记录的不再是简单的SQL语句了,而是记录表的行更改情况.从MySQL5.1版本开始,如果设置了binlog_format
为ROW
,可以将InnoDB
的事务隔离级别设置为READ COMMITTED
,以获得更好的并发性. -
MIXED
格式,默认采用STATEMENT
格式进行二进制日志文件的记录,但是在一些情况下会使用ROW
格式.可能的情况有:- 表的存储引擎未NDB,此时对表的DML操作都会以ROW格式记录.
- 使用
UUID(),USER(),CURRENT_USER()
的不确定函数. - 使用了
INSERT DELAY
语句. - 使用了用户自定义函数(UDF).
- 使用了临时表.
binlog
文件内容
binlog
会存储以下信息:- 更新语句的类型:INSERT、UPDATE或DELETE.
- 被更新的表的名称和库名.
- 更新前和更新后的数据值.
- 更新的时间戳和事务ID.
- 执行更新操作的线程ID.
- MySQL所使用的字符集.
- 是否存在外键依赖关系.
1 | # at 20707752 |
- 在第一行中,
#at
后面的数字表示二进制日志文件中事件的起始位置(文件偏移量). - 第二行包含了语句在服务器上被启用的时间戳.时间戳后面跟着
server id,end_log_pos,thread_id,exec_time
和error_code
server id
: 产生该事件的服务器的server_id
值(240925)end_log_pos
: 下一个事件的开始位置thread_id
: 指示哪个线程执行了该事件.exec_time
: 在主服务器上,它代表执行事件的事件;在从服务器上,它代表从服务器的最终执行时间与主服务器的开始时间之间的差值,这个差值可以作为备份相对于主服务器滞后多少的指标.error_code
: 代表执行事件的结果.零意味着没有错误发生.
binlog
有什么用?
-
其主要作用包括:
-
数据恢复:
binlog
记录了数据库的所有更新操作,包括插入、更新和删除等操作,因此可以用于数据恢复.例如,如果一条误删除数据的SQL语句被执行了,可以根据从binlog
中找到该操作的时间戳等关键信息来还原数据. -
主从复制:
binlog
也是MySQL中用于实现主从复制的关键机制之一.在主数据库上,binlog
记录了所有写操作的信息,可以将这些信息重新应用到从服务器中,从而保持所有数据的一致性. -
增量备份:
binlog
可用于实现MySQL逐增备份(incremental backup)的机制.通过备份存储在binlog
文件中的更新操作,可以在每次备份中仅备份新增的数据,从而提高备份效率. -
审计与安全:
binlog
中包含了大量的数据库操作信息,例如执行每个更新操作的时间和用户等信息,在数据库审计和安全方面具有重要作用.
-
-
总之,由于
binlog
记录了MySQL数据库中所有的写操作信息,因此可以用于数据库的数据恢复、主从复制和备份等方面.同时,binlog
也可以用于数据库的安全审计和追踪
如何使用binlog
?
- 要启动二进制日志,必须设置
log_bin
和server_id
并重新启动服务器.可以在log_bin
内提及path
和base
名称.- 例如
log_bin
设置为/data/mysql/binlogs/server1
,二进制日志存储在/data/mysql/binlogs
文件夹中名为server1.000001,server1.000002
等日志文件中.
- 例如
- 每当服务器启动或刷新日志时,或者当前日志的大小达到
max_binlog_size
时,服务器都会在系列中创建一个新文件.每个二进制日志的位置都在server1.index
文件中维护.
启用二进制日志
-
在MySQL的配置文件
my.cnf
中添加1
2
3[mysqld]
log_bin = /data/mysql/binlogs/server1
server_id = 100 -
重新启动MySQL服务器:
sudo systemctl restart mysql
binlog
查看
1 | mysql> show variables like 'log_bin%'; |
1 | mysql> set session binlog_format = statement; |
- 可以通过命令
SHOW BINLOG EVENTS
可以查看二进制日志中的记录.
1 | mysqlbinlog -vv --start-position=155 binlog.000089 |
禁用会话的二进制日志
-
有些情况下不希望将执行语句复制到其他服务器上.为此,可以使用以下命令来禁用该会话的二进制日志:
1
SET SQL_LOG_BIN = 0;
-
在这条语句后的所有SQL都不会被记录到二进制日志中,不过这仅仅是针对该会话的.
-
要重新启用二进制日志,可以执行以下操作:
1
SET SQL_LOG_BIN = 1;
清理二进制日志
- 使用
binlog_expire_logs_seconds
和expire_logs_days
设置日志的到期时间.- 如果想以天为单位设置到期时间,请设置
expire_logs_days
.例如,如果要删除两天之前的所有二进制日志,请SET @@global.expire_logs_days = 2
,若将该值设置为0,则禁用设置会自动到期. - 若要设置更细粒度的到期时间,可以使用
binlog_expire_logs_seconds
,它能够以秒为单位来设置二进制日志过期时间. binlog_expire_logs_seconds
和expire_logs_days
的效果是叠加的.- 例如
expire_logs_days = 1
并且binlog_expire_logs_seconds = 43200
则二进制日志就会每1.5
天清除一次.
- 例如
- 在
MySQL
中binlog_expire_logs_seconds
和expire_logs_days
必须设置为0,以禁止自动清除二进制日志
- 如果想以天为单位设置到期时间,请设置
- 要手动清除日志,可以执行
PURGE BINARY LOGS TO '<file_name>'
,例如,有server1.000001,server1.000002,server1.000003,server1.000004
如果执行PURGE BINARY LOGS TO 'server1.000004'
则从server1.000001
到server1.000003
的所有文件都会被删除,但文件server1.000004
不会被删除. - 要删除所有二进制日志并再次从头开始,请执行
RESET MASTER
binlog
的缺点
- 事务不能太大,否则会导致二进制日志非常大,一个大事务的提交会非常慢
- 处理办法:
- 设计时,把
DELETE
删除操作转化为DROP TABLE/PARTITION
操作 - 业务设计时,把大事务拆成小事务
- 设计时,把