本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
前言
日志是MySQL数据库的重要组成部分,记录着数据库运行期间各种状态信息。MySQL中日志类型有很多种,但对于开发来说,最常见和最重要的就是binlog、redolog和undolog。今天先简单介绍一下binlog。
前置知识
简单说一下,逻辑日志和物理日志的区别吧
- 逻辑日志:可以简单得理解为
sql语句,如insert into tbl value(...); - 物理日志:
MySQL中数据都是保存在数据页中的,物理日志记录的是数据页上的变更,如新增的一条数据具体存储在哪个数据页上的哪一行;
binlog
binlog是MySQL Server层记录的日志,也就是说,不管MySQL使用的什么存储引擎,都会有bin log产生。binlog是MySQL中最重要的日志,它记录了所有的DDL和DML(除了查询语句)语句,即所有修改数据的操作,以二进制的形式存储在磁盘中,binlog是一种逻辑日志。
binlog 作用
- 主从复制:在
Mater端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致; - 数据恢复:基于时间点,可以通过
mysqlbinlog工具来恢复数据;
binlog 主从复制原理
MySQL主从同步主要依靠binlog来实现。这里简单介绍一下基本原理。
流程大致如下:
-
主节点 binlog dump 线程:当从节点连接主节点时,主节点会创建一个
log dump线程,用于发送binlog的内容。在读取binlog中的操作时,此线程会对主节点上的binlog加锁,当读取完成,甚至在发动给从节点之前,锁会被释放 -
从节点I/O线程:当从节点上执行
start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的binlog。I/O线程接收到主节点binlog dump进程发来的更新之后,保存在本地relaylog中; -
从节点SQL线程:
SQL线程负责读取relaylog中的内容,解析成具体的操作并执行,最终保证主从数据的一致性;
binlog的内容
上面说了,binlog是一种逻辑日志,可以简单得理解为sql语句,但是实际上还包含着执行的sql语句的反向逻辑。delete对应着delete本身以及反向的insert信息;update包含着对应的update执行前后数据行的相关信息;insert包含自身的insert以及对应的delete信息。
binlog的格式
binlog共有三种格式,分别是statement、row以及mixed。MySQL 5.7.7版本之前默认使用的是statement,MySQL 5.7.7之后默认使用的是row。日志的格式可以通过my.ini配置文件中的binlog-format来修改。
-
statement:基于sql语句的复制(statement-based replication,SBR),每一条修改数据的sql语句都会记录到binlog中。- 优点:不需要具体记录某一行的变化,节约空间,减少
io,提高性能; - 缺点:在执行
sysdate()或者sleep()等操作的时候,可能导致主从数据不一致的情况;
- 优点:不需要具体记录某一行的变化,节约空间,减少
-
row:基于行记录的复制(row-based replication,RBR),不记录sql语句上下文相关信息,而是记录哪条记录被修改的细节。-
优点:非常详细地记录每一行记录修改的细节,因而不会出现数据无法被正确复制的情况;
-
缺点:由于会非常详细地记录每一条记录修改的细节,这样会产生大量的日志内容。假设现在有一条
update语句,修改了很多条记录,则每条修改记录都会记录到binlog中。特别地,**alter table**这个操作,由于表结构的变化,每行记录都会发生变化,导致日志量暴增;
-
-
mixed:根据上面所说的,statement和row各有优缺点,因此出现了mixed这个版本,将这二者进行混合。一般情况下使用statement格式来进行保存,当遇到statement无法解决时,切换为row格式来进行保存。
新版本(MySQL 5.7.7之后)默认使用的row格式,这里的row也做了相应的优化,在遇到alter table这个操作时采用statement格式进行记录,其余操作仍然使用row格式。
binlog的刷盘时机
对于InnoDB存储引擎来说,只有在事务提交的时候才会记录binlog,此时记录还在内存中,MySQL通过sync_binlog来控制binlog的刷盘时机,取值范围为0-N:
- 0:不强制刷到磁盘,由系统自行判断何时写入磁盘中;
- 1:每次提交后都要将
binlog写入磁盘中; N:每N个事务,才会将binlog写入磁盘中;
binlog的物理文件大小
在my.ini配置文件中,可以通过max_binlog_size来配置binlog的大小。当日志量超过binlog文件的大小时,系统会重新生成一个新的文件来继续保存文件。当一个事务比较大时,或者是当日志越来越多的时候,此时占据的物理空间太大怎么办?MySQL提供了一种自动删除的机制,还是在my.ini配置文件中,可以通过配置expire_logs_days 这个参数来解决,单位为天。当这个参数为0,表示永不删除;为N时,表示第N天后自动删除。