日志(三)
- 写入机制
binlog的写入时机也非常简单,事务执行过程中,先把日志写到 binlog cache ,事务提交的时候,再把binlog cache写到binlog文件中。因为一个事务的binlog不能被拆开,
无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache
# 当事务提交后,日志会保存到binlog cache中
# 当事务还没提交时,mysql突然挂了,日志不会保存到binlog cache中
# 当事务提交后,mysql突然挂了,会保存在文件系统缓存中
# 如果整个系统突然挂了,则文件系统缓存中的数据也会丢失
write和fsync的时机,可以由参数 sync_binlog 控制,默认是 0 。为0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync。虽然性能得到提升,
但是机器宕机,page cache里面的binglog 会丢失
为了安全起见,可以设置为 1 ,表示每次提交事务都会执行fsync,就如同redo log 刷盘流程一样。
最后还有一种折中方式,可以设置为N(N>1),表示每次提交事务都write,但累积N个事务后才fsync。
- binlog与redolog对比
redo log 它是 物理日志 ,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB 存储引擎层产生的。
而 binlog 是 逻辑日志 ,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server 层。
- 两阶段提交
在执行更新语句过程,会记录redo log与binlog两块日志,以基本的事务为单位,redo log在事务执行过程中可以不断写入,
而binlog只有在提交事务时才写入,所以redo log与binlog的 写入时机 不一样
-
例如我们执行某个事务,记录到redo log后,mysql突然出现异常,导致没有及时将事务记录到bin log中
-
在主从2台服务器中,主从同步时,数据不一致
-
解决方案是,将写入redo log日志的步骤拆分为2步,先写入redo log,在写入bin log,最后提交redo log
-
最后提交redo log时发生异常,并不会回滚事务,它会执行上图框住的逻辑,虽然redo log是处于prepare阶段,但是能通过事务id找到对应的binlog日志,所以MySQL认为是完整的,就会提交事务恢复数据
-
中继日志
中继日志只在主从服务器架构的从服务器上存在。从服务器为了与主服务器保持一致,要从主服务器读取二进制日志的内容,并且把读取到的信息写入本地的日志文件中,
这个从服务器本地的日志文件就叫中继日志 。然后,从服务器读取中继日志,并根据中继日志的内容对从服务器的数据进行更新,完成主从服务器的 数据同步
搭建好主从服务器之后,中继日志默认会保存在从服务器的数据目录下。
文件名的格式是: 从服务器名 -relay-bin.序号 。中继日志还有一个索引文件: 从服务器名 -relaybin.index ,用来定位当前正在使用的中继日志。
- 恢复的典型错误
如果从服务器宕机,有的时候为了系统恢复,要重装操作系统,这样就可能会导致你的 服务器名称 与之前 不同 。而中继日志里是 包含从服务器名 的。
在这种情况下,就可能导致你恢复从服务器的时候,无法从宕机前的中继日志里读取数据,以为是日志文件损坏了,其实是名称不对了
解决的方法也很简单,把从服务器的名称改回之前的名称