mysql log

sanlanlan 2021-3-1 标签: mysql 浏览:749 评论:0

1.什么是binlog?

binlog记录了数据库表结构和表数据变更,比如update/delete/insert/truncate/create。它不会记录select(因为这没有对表没有进行变更)

2.binlog长什么样?

binlog我们可以简单理解为:存储着每条变更的SQL语句

默认情况下binlog日志是二进制格式,无法直接查看

可以使用mysqlbinlog来查看,mysqlbinlog是mysql官方提供的一个binlog查看工具。



3.binlog一般用来做什么

主要有两个作用:复制和恢复数据

1.MySQL在公司使用的时候往往都是一主多从结构的,从服务器需要与主服务器的数据保持一致,这就是通过binlog来实现的
2.数据库的数据被干掉了,我们可以通过binlog来对数据进行恢复。

因为binlog记录了数据库表的变更,所以我们可以用binlog进行复制(主从复制)和恢复数据。



二、什么是redo log

update user_table set name='java3y' where id = '3'

MySQL执行这条SQL语句,肯定是先把id=3的这条记录查出来,然后将name字段给改掉。这没问题吧?


实际上Mysql的基本存储结构是页(记录都存在页里边),所以MySQL是先把这条记录所在的页找到,然后把该页加载到内存中,将对应记录进行修改。

P:现在就可能存在一个问题:如果在内存中把数据改了,还没来得及落磁盘,而此时的数据库挂了怎么办?显然这次更改就丢了。

P:如果每个请求都需要将数据立马落磁盘之后,那速度会很慢,MySQL可能也顶不住。所以MySQL是怎么做的呢?


MySQL引入了redo log,内存写完了,然后会写一份redo log,这份redo log记载着这次在某个页上做了什么修改。

其实写redo log的时候,也会有buffer,是先写buffer,再真正落到磁盘中的。至于从buffer什么时候落磁盘,会有配置供我们配置。


写redo log也是需要写磁盘的,但它的好处就是顺序IO(我们都知道顺序IO比随机IO快非常多)。

所以,redo log的存在为了:
当我们修改的时候,写完内存了,但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以根据redo log来对数据进行恢复。
因为redo log是顺序IO,所以写入的速度很快,并且redo log记载的是物理变化(xxxx页做了xxx修改),文件的体积很小,恢复速度很快。


redo log

什么时候释放:

    当对应事务的脏页写入到磁盘之后,redo log的使命也就完成了,重做日志占用的空间就可以重用(被覆盖)。



三、binlog和redo log      区别

1.存储的内容
binlog记载的是update/delete/insert这样的SQL语句,
而redo log记载的是物理修改的内容(xxxx页修改了xxx)。

所以在搜索资料的时候会有这样的说法:redo log 记录的是数据的物理变化,binlog 记录的是数据的逻辑变化

2.功能
redo log的作用是为持久化而生的。写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,
将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。

binlog的作用是复制和恢复而生的。

主从服务器需要保持数据的一致性,通过binlog来同步数据。
如果整个数据库的数据都被删除了,binlog存储着所有的数据变更情况,那么可以通过binlog来对数据进行恢复。

又看到这里,你会想:”如果整个数据库的数据都被删除了,那我可以用redo log的记录来恢复吗?
“不能因为功能的不同,redo log 存储的是物理数据的变更,如果我们内存的数据已经刷到了磁盘了,那redo log的数据就无效了。

所以redo log不会存储着历史所有数据的变更,文件的内容会被覆盖的。


3.binlog和redo log 写入的细节

redo log是MySQL的InnoDB引擎所产生的。

binlog无论MySQL用什么引擎,都会有的。


InnoDB是有事务的:持久性就是靠redo log来实现的(如果写入内存成功,但数据还没真正刷到磁盘,如果此时的数据库挂了,我们可以靠redo log来恢复内存的数据,这就实现了持久性)。


4.写入时间

redo log事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录。

于是新有的问题又出现了:
我写其中的某一个log,失败了,那会怎么办?
现在我们的前提是先写redo log,再写binlog,我们来看看:

1.如果写redo log失败了,那我们就认为这次事务有问题,回滚,不再写binlog。
2.如果写redo log成功了,写binlog,写binlog写一半了,但失败了怎么办?
    我们还是会对这次的事务回滚,将无效的binlog给删除(因为binlog会影响从库的数据,所以需要做删除操作)
3.如果写redo log和binlog都成功了,那这次算是事务才会真正成功。


SO:简单来说:MySQL需要保证redo log和binlog的数据是一致的,如果不一致,那就乱套了。

1.如果redo log写失败了,而binlog写成功了。那假设内存的数据还没来得及落磁盘,机器就挂掉了。那主从服务器的数据就不一致了。(从服务器通过binlog得到最新的数据,而主服务器由于redo log没有记载,没法恢复数据)
2.如果redo log写成功了,而binlog写失败了。那从服务器就拿不到最新的数据了。

5.两阶段    
MySQL通过两阶段提交来保证redo log和binlog的数据是一致的。

阶段1:InnoDB redo log 写盘,InnoDB 事务进入 prepare 状态

阶段2:binlog 写盘,InooDB 事务进入 commit 状态

每个事务binlog的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,恢复过程中,binlog 最后一个 XID event 之后的内容都应该被 清除


四、什么是undo log

undo log主要有两个作用:回滚和多版本控制(MVCC)


1.在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚

2.undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。

我们要update一条记录时,它会记录一条对应相反的update记录。


因为undo log存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。


 什么时候产生:
      事务开始之前,将当前是的版本生成undo log,undo 也会产生 redo 来保证undo log的可靠性

什么时候释放:
      当事务提交之后,undo log并不能立马被删除,而是放入待清理的链表,
           由purge线程判断是否由其他事务在使用undo段中表的上一个事务之前的版本信息,决定是否可以清理undo log的日志空间。



问题一:Mysql怎么保证一致性的?

从数据库层面,数据库通过原子性、隔离性、持久性来保证一致性。也就是说ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔离性)、D(持久性)是手段,是为了保证一致性,数据库提供的手段。
数据库必须要实现AID三大特性,才有可能实现一致性。例如,原子性无法保证,显然一致性也无法保证。

问题二: Mysql怎么保证原子性的?
    利用Innodb的undo log。
undo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的sql语句,他需要记录你要回滚的相应日志信息。


问题三: Mysql怎么保证持久性的?
    利用Innodb的redo log。

采用redo log的好处?

其实好处就是将redo log进行刷盘比对数据页刷盘效率高,具体表现如下


    1.redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。
    2.redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。

问题四: Mysql怎么保证隔离性的?
    利用的是锁和MVCC机制


参考资料

https://www.cnblogs.com/f-ck-need-u/p/9010872.html

本文相关标签: mysql log

发表评论: