在mysql中,我们称二进制日志为binlog,
- 工作内容:它记录了所有修改了数据库的语句,或者有可能会改变数据库的语句,换句话说,select、show这种不修改数据库的操作,二进制日志是不会进行记录的,
- 用 途:二进制日志主要用于时间点恢复(备份恢复),以及主从复制结构。
binlog相关概念
浅谈binlog时间点恢复:
生产环境-备份恢复案例:
假如我们每天晚上12点进行一次数据库备份,此处不考虑数据量,备份时间等其他因素,那么在本次备份完成后到下次备份开始前的这段时间段中,如果数据库服务崩溃了,我们应该怎样恢复呢?
如果我们只依靠上一次的数据库备份进行恢复,那么我们最多只能恢复到上一个12点时的数据,但是12点以后的数据则会丢失,所以,我们还需要依靠二进制日志(binlog),
- 我们先用上一次的备份将数据库恢复至最近一次12点时的样子,
- 再利用binlog,将12点之后的所有操作"重放"一遍,由于上次备份之时到数据库崩溃之时之间的所有操作完完全全的重新执行了一遍,所以我们可以将数据库中的数据恢复至崩溃之时的样子,而不至于丢失数据,
这就是binlog用于恢复时的作用,如果你使用过oracle,那么你肯定会认为,mysql中的binlog与oracle中的归档日志特别像,其实它们存在的目的都是差不多的。
引出binlog概念:
我们对binlog已经有了初步的概念,即:binlog记录了所有的修改了数据库的语句。
binlog 3 种记录方式:
statement模式:
记录对数据库做出修改的语句,比如,update A set test='test',如果使用statement模式,那么这条update语句将会被记录到二进制日志中,使用statement模式时,
优点:是binlog日志量少,IO压力小,性能较高,
缺点:是为了能够尽量的完全一致的还原操作,除了记录语句本身以外,可能还需要记录一些相关的信息,而且,在使用一些特定的函数时,并不能保证恢复操作与记录时完全一致。
row模式:
记录对数据库做出修改的语句所影响到的数据行以及这些行的修改,比如,update A set test='test',如果使用row模式,那么这条update语句所影响到的行所对应的修改,将会记录到binlog中,
示例:比如,A表中有1000条数据,那么当执行这条update语句以后,由于1000条数据都会被修改,所以会有1000行数据被记录到二进制日志中,以及它们是怎样被修改的,
优点:是能够完全的还原或者复制日志被记录时的操作,
缺点:是记录日志量较大,IO压力大,性能消耗较大。
mixed模式:
混合使用上述两种模式,一般的语句使用statment方式进行保存,如果遇到一些特殊的函数,则使用row模式进行记录,这种记录方式被称之为mixed,看上去这种方式似乎比较美好,但是在生产环境中,为了保险起见,一般会使用row模式。
binlog 之 事件与位置:
二进制日志文件,有"事件"和"位置"的概念,什么是事件呢?通俗的讲,我们可以把binlog中的每一条记录当做一个"事件",因为binlog记录了所有对数据库进行的修改,所以,我们可以认为,数据库的修改被记录到二进制日志中,这些记录每一条都可以理解为一个"事件",由于二进制日志文件是二进制的,所以,我们可以把整个二进制文件想象成一个字节序列,假设,
- 事件1:二进制日志文件刚开始是空的,从第1个字节开始记录,假设记录第一个"事件"(第一条记录),需要15个字节,那么第一个事件的开始"位置"就是1,结束"位置"就是15,
- 事件2:由于前15个字节已经被第一个事件占用,那么当我们想要通过二进制日志记录第二个事件时,则需要从第15个字节向后开始记录,假设记录第二个"事件"需要20个字节,那么第二个事件在binlog中的起始"位置"就是15,结束"位置"就是35,
以此类推,这就是二进制日志中,"事件"与"位置"的概念,"事件"被称为events,"位置"被称为position,如果你现在还不能很清晰的理解他们,没有关系,当我们动手实践的时候,你自然会明白。
binlog 相关参数:
binlog_format:
临时生效:管理员可以使用binlog_format变量设置二进制日志的记录方式,
永久生效:
为了使配置永久生效,我们可以在server端的my.cnf配置文件中加入如下配置:
[mysqld] binlog_format=row
上述配置表示使用row模式记录binlog。
log_bin:
- 作用:用于控制是否开启二进制日志,而且这是一个只读变量;
- 具体使用方法:
默认情况下,当我们启动数据库以后,在当前数据库连接中查看此变量的值,此变量值可能为OFF,表示不记录二进制日志,如果想要记录二进制日志,只需将此值设置为二进制日志的文件名即可。
但是需要注意的是,我们无法在当前会话中使用set命令设置log_bin的值,因为它是一个只读变量,我们只能通过修改my.cnf的方式,设置log_bin的值,
假设,我们编辑my.cnf文件,设置log_bin的值为mybinlog,那么,在mysql的数据目录中,将会自动生成一个以mybinlog为文件名前缀的二进制日志文件,如果想要再次禁用binlog,只需
要将log_bin这一行配置从my.cnf文件中注释即可,或者将其删除,重启mysql服务后,再次查看log_bin的值,其值为OFF, - 注意:
- 不要直接在my.cnf文件中将log_bin的值设置为ON或者OFF,如果这样做,你将会看到以ON或者OFF为文件名前缀的二进制日志文件。
- 换句话说,如果my.cnf配置文件中没有log_bin的配置,则表示未开启二进制日志,如果my.cnf中存在log_bin的配置,那么则表示开启了二进制日志,同时二进制日志文件的名称将会以log_bin对应的值为文件名前缀,
- 同时,二进制日志文件的后缀名会进行自动编号,每次日志滚动后,后缀名编号自动加1。
sql_log_bin:
- 作用:用于标识当前会话中的操作是否会被记录于二进制日志,
- 此变量值设置为ON,则表示在当前数据库连接中,对数据库进行修改的语句将会被记录到binlog中,
- 此变量值设置为OFF,则表示在当前数据库连接中,对数据库进行的修改的语句将不会被记录到binlog中
- 主从复制的使用:
在主从复制结构中,这些语句由于没有被binlog记录,所以也不会同步到从节点中。换句话说,即使在my.cnf配置文件中设置了log_bin的值,当前会话中,如果sql_log_bin的值设置为OFF,当前会话的操作也不会记录在二进制日志中。
- 注意:
- sql_log_bin是一个会话界别的变量,只能在当前会话中使用set sql_log_bin命令进行设置,不能使用set global sql_log_bin命令进行设置,因为它是会话级别的变量
- sql_log_bin也不能配置在my.cnf文件中,否则可能会无法启动mysql
max_binlog_size :
设置单个二进制日志文件的最大大小,以字节为单位,超过此值大小,则二进制日志文件会自动滚动,比如设置为500M为524288000
sync_binlog:
- 作用:二进制日志刷新缓存机制;
- 值=1:表示每1次事务提交之后,都会立即将内存中的二进制日志立即同步到磁盘中的二进制日志文件中;
- 值=0:表示当事务提交之后,mysql不会立即将内存中的binlog刷写到磁盘中的binlog日志文件中,而是由文件系统决定什么时候刷写,这可能取决于文件系统的缓存机制;
- 值=N:假设将此值设置为3,则表示每3次事务提交后,将binlog从内存刷写到磁盘一次
- 注意:
- 当此值设置为0时,一旦操作系统宕机,那么将丢失未从内存中同步到磁盘中的binlog,所以,当此值设置为0时,安全性最差,但是性能最高,当此值设置为1时,安全性最高,性能最差;
- 当值=N时,值设置的越大,有可能丢失的日志数据将会越多,当然,性能会越好
binlog相关命令:
查看二进制日志文件列表:
show master logs; show binary logs;
查看当前正在使用的二进制日志文件
mysql> show master status;
查看二进制日志文件中的事件
mysql> show binlog events; mysql> show binlog events in 'mybinlog.000001'; mysql> show binlog events in 'mybinlog.000001'from 245; mysql> show binlog events in 'mybinlog.000001'limit 3; mysql> show binlog events in 'mybinlog.000001'limit 2,5; mysql> show binlog events in 'mybinlog.000001'from 245 limit 10; mysql> show binlog events in 'mybinlog.000001'from 245 limit 4,20;
mysqlbinlog命令:
# 查看mybinlog.000001的二进制文件: [root@localhost ~]# mysqlbinlog mybinlog.000001 # 从指定位置开始查看二进制日志 [root@localhost ~]# mysqlbinlog --start-position 415 mybinlog.000001 # 从哪个位置开始,到那个位置结束,查看这之间的二进制日志文件 [root@localhost ~]# mysqlbinlog --start-position 317 --stop-position 442 mybinlog.000001 # 从指定的时间开始查看,比如,查看2017年3月4日10点40以后的日志 [root@localhost ~]# mysqlbinlog --start-datetime "2017-3-4 10:40:00" mybinlog.000001 # 也可以指定结束时间. [root@localhost ~]# mysqlbinlog --start-datetime "2017-3-4 10:40:00" --stop-datetime "2017-3-4 10:55:00" mybinlog.000001