当前位置: 首页 > 科技观察

MySQL的binlog的三种格式,太好玩了!

时间:2023-03-12 03:51:05 科技观察

MySQL中比较重要的日志有binlog(归档日志)、redolog(重做日志)和undolog,所以和我们这篇文章相关的主要是binlog,另外两个日志等松哥在的时候分享给大家将来免费。让我详细介绍一下。1、binlogbinlog中文一般称为archivedlog。如果你之前看过松哥发的MySQL主从构建,应该对这篇日志有印象。我们在搭建MySQL主从的时候,离不开binlog(传送门:MySQL8主从复制踩坑指南)。Binlog是MySQLServer层的日志,不是存储引擎自带的日志。它记录了所有的DDL和DML(不包括数据查询语句)语句,并以事件的形式记录下来,包括语句执行所消耗的时间等,需要注意的是:binlog是一种逻辑日志,它记录SQL语句的原始逻辑,比如对某个字段+1。注意这里和redolog的物理日志不同(在某个数据页上面做了什么修改)。binlog文件写满后,会自动切换到下一个日志文件继续写入,不会覆盖之前的日志。这也不同于重做日志。redolog是循环写入的,即后面的写入可能会覆盖前面的。进入。一般来说,我们在配置binlog的时候,可以指定binlog文件的有效期,这样过期后,日志文件会自动删除,避免占用更多的存储空间。根据MySQL官方文档,开启binlog后,会有1%左右的性能损失,但这还是可以接受的。一般来说,binlog有两个重要的使用场景:MySQL主从复制:在宿主机上启用Binlog,master将binlog同步到slave,slave通过binlog同步数据,从而实现master与从属之间的数据同步奴隶。MySQL数据恢复,使用mysqlbinlog工具结合binlog文件,可以将数据恢复到过去的某个时间点。2.配置binlog为了演示方便,宋哥在Docker中安装了MySQL,我们就以此为例开始今天的演示。不知道怎么用docker的小伙伴可以在公众号后台回复docker,里面有宋哥写的教程。首先我们在docker中安装MySQL,然后进入容器,使用如下命令查看binlog是否开启:这个OFF表示binlog处于关闭状态,没有开启。binlog日志的格式可以通过以下命令查看,如下:可以看到,这个binlog的格式是ROW。这里涉及到一个问题,binlog的格式。2.1binlog的格式binlog有三种格式:Statement(Statement-BasedReplication,SBR):每条将修改数据的SQL都会记录在binlog中。行(Row-BasedReplication,RBR):不记录SQL语句的上下文信息,只保存哪条记录被修改了。混合(Mixed-BasedReplication,MBR):Statement和Row的混合。2.1.1StatementStatement模式只记录执行的SQL,不需要记录每一行数据的变化,所以大大减少了binlog的日志量,避免了大量的IO操作,对系统性能的影响得到改善。但是,正是因为Statement模式只记录了SQL,如果某些SQL包含函数,可能会出现执行结果不一致的情况。例如uuid()函数每次执行都会生成一个随机字符串。uuid记录在master中。同步到slave后,再次执行,得到另一个结果。因此在使用Statement格式时会存在一些数据一致性问题。2.2.2Row从MySQL5.1.5开始,binlog引入了Row格式。Row格式不记录与SQL语句上下文相关的信息,只需要记录某条记录是如何被修改的。Row格式的日志内容会清楚的记录每一行数据修改的细节,这样就不会出现Statement中的数据无法正常复制的情况。但是Row格式也有一个很大的问题,就是日志量太大,尤其是批量update、整表delete、altertable等操作。由于需要记录每一行数据的变化,所以这时候会产生大量的日志。日志也会带来IO性能问题。2.2.3Mixed从MySQL5.1.8开始,MySQL引入了Mixed格式,其实就是Statement和Row的结合。Mixed模式下,系统会自动判断使用Statement还是Row:一般的statement修改使用Statement格式保存binlog;对于一些不能准确完成主从复制操作的Statement,采用Row格式保存binlog。在Mixed模式下,MySQL会根据执行的每条具体的SQL语句,对记录的日志格式进行不同的处理,即Statement和Row二选一。2.2配置接下来我们看一下binlog的配置。2.2.1开启binlog开启binlog主要是修改容器的/etc/mysql/mysql.conf.d目录下的MySQL配置文件mysqld.cnf。对于这个配置文件,我们做如下修改:#该参数表示开启binlog功能,指定binlog的存放目录log-bin=javaboy_logbin#设置一个binlog文件的最大字节#设置最大100MBmax_binlog_size=104857600#设置binlog文件的大小有效期(单位:天)expire_logs_days=7#binlog日志只记录指定库的更新(配置主从复制时使用)#binlog-do-db=javaboy_db#binlog日志不记录指定库的更新(配置master-slave复制时会用到)#binlog-ignore-db=javaboy_no_db#多少次写入缓存,刷新一次磁盘,默认0表示这个操作是由操作系统根据自己的负载决定多久写一次磁盘#1表示每次事务commit都会立即写入磁盘,n表示n个事务会被提交写入thedisksync_binlog=0#获取当前服务的唯一id(MySQL5.7后需要配置)server-id=1各项配置的含义松哥已经在看中描述了。截图如下:配置完成后,执行如下命令重启mysql容器(mysql1这里是我容器的名字):dockerrestartmysql1重启后,再次执行showvariableslike'log_bin%';可以看到binlog已经开启。除了log_bin这个变量,还有两个变量名值得我们注意:log_bin_basename:这个是以后生成的binlog日志文件的名字前缀,也就是说按照目前看到的配置,binlog以后生成的日志文件名为javaboy_logbin.xxx,这个文件会用来记录所有的DDL和DML语句事件。log_bin_index:这个是binlog的索引文件,里面保存了所有的binlog目录,因为可能有多个binlog。我们可以看一下当前的javaboy_logbin.index文件:可以看到,目前只有一个logbin文件。2.2.2修改binlog_formatbinlog_format有几种不同的修改方式:修改当前session的binlog_format,该修改只对当前session有效;也可以修改全局的binlog_format,这个修改会在重启MySQL后失效:如果想一劳永逸可以修改/etc/mysql/mysql.conf.d/mysqld.cnf配置文件。在配置文件中,添加binlog_format选项,如下:这是永久修改。3.常用的binlog操作下面介绍几种常用的binlog操作命令。查看所有binlog日志我们可以通过以下方式查看binlog日志列表:showmasterlogs;可以看到,我这里目前只有一个日志文件,文件名为javaboy_logbin.000001,file_size表示这个文件占用的字节大小是154,如下:此时可以看到最新的binlog日志文件名和上次操作事件的Position值(这个值有什么用,后面会给大家详细介绍)。刷新binlog一般情况下,一个binlog写满后,会自动切换到下一个binlog开始写入,但是我们也可以执行一个flushlogs命令来手动刷新binlog。手动刷新binlog后,会生成一个新的binlog日志文件,然后所有的binlog日志都会记录在新的文件中。如下:从上图可以看出,我们刷新日志后,可以通过showmasterlogs查看日志,发现生成了新的日志文件,再通过showmaster查看最新的日志文件信息status,发现也变成了javaboy_logbin.000002。重置binlogresetmaster可以重置binlog日志文件,让日志重新从000001开始记录,但是如果当前master有一个或多个slave在运行,这个命令就不起作用了(因为slave是使用binlog来实现数据库同步的,host已经清除了binlog,slave会报找不到binlog的错误)。查看binlog由于binlog是二进制日志文件,如果直接打开肯定是看不到的:看不到任何有用的信息。为了查看binlog,MySQL官方为我们提供了两个工具。让我们一一看看。首先是mysqlbinlog命令,如下:虽然看起来乱七八糟,但仔细看其实还是有迹可循的。因为这里是新安装的数据库,所以我只是新建了一个名为javaboy的库,然后创建了一个名为user的表并添加了两条数据,其他什么都没做,所以我们实际创建库的脚本可以在各种文档中找到。生成的日志文件中有一个end_log_pos,就是日志文件的pos点,对以后的数据恢复会有用。然而,这种观看方式对用户来说并不友好。我们说binlog是按照事件来记录日志的,那么如果能按照事件来查看日志就更好了。我们来看看下面的命令:showbinlogevents[IN'log_name'][FROMpos][LIMIT[offset,]row_count];意思是以事件的形式查看binlog,涉及到几个参数:log_name:可以指定要查看的binlog日志文件的名称,如果不指定,表示查看最早的binlog文件。pos:从哪个pos点开始查看。所有记录在binlog中的操作都有一个pos点。这实际上相当于我们可以指定从哪个操作开始查看日志。如果不指定,就是从binlog的开头开始查看。offset:这个是偏移量,如果不指定,默认为0。row_count:查看多少行记录,如果不指定,表示查看全部。我们来看一个简单的例子:showbinlogeventsin'javaboy_logbin.000001';这样就清楚多了,我们可以看到之前的所有操作,例如:在Pos219-322之间创建了一个library。在Pos387-537之间创建了一个表。在Pos677-780之间添加一条记录。...这其实就是Row格式的binlog。4.总结好了,今天的文章主要是给小伙伴们分享MySQL的binlog日志,主要是一些理论知识。在下一篇文章中,宋大哥将通过两个具体案例来论证不同binlog_formats的存在。问题。本文转载自微信公众号“江南的一场小雨”,可通过以下二维码关注。转载本文请联系江南一点鱼公众号。