首页 > 数据库 >MySQL - 日志

MySQL - 日志

时间:2024-01-21 22:49:15浏览次数:37  
标签:binlog 事务 log 提交 MySQL 日志 redo

1. 回滚日志(undo log)

作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读

内容:逻辑格式的日志(当delete一条记录是,记录一条对应的insert记录,反之亦然),在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态

释放:当事务提交之后,undo log并不能立马被删除,而是放入待清理的链表,通过判断是否由其他事务在使用undo的版本信息,决定是否可以清理

1)保证原子性,在数据修改的时候,不仅记录了redo log,还记录了对应的undo,如果因为某些原因事务失败而回滚,可以借助该undo进行回滚。

2)当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚

3)当读取带某一行的其他事务锁定时,它可以从undo log中分析出改行记录以前的数据是什么,从而提供该行版本信息,让用户实现MVCC

2. 重做日志(redo log)

作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启MySQL时,根据redo log进行重做,从而达到事务的持久性这一特性

内容:物理格式的日志,记录的是物理数据页面的修改的信息

产生:事务开始之后就产生redo log,不是随着事务的提交才写入的

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

3. 二进制日志(bin log)

作用:用于在主从复制中,从库利用主库上的binlog进行重播,实现主从同步;用于数据库的基于时间点的还原。

内容:逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。 而且还包括了执行的sql语句(增删改)反向的信息

产生:事务提交的时候,一次性将事务中的sql语句(一个事务可能对应多个sql语句)按照一定的格式记录到binlog中(对于较大事务的提交,可能会变得比较慢一些)

注意:与redo log的差异:redo log不是在事务提交的时候刷新到磁盘,因此对于事务的提交,即便是较大的事务,提交(commit)都是很快的

释放:binlog的默认是保持时间由参数expire_logs_days配置,在生成时间超过配置的天数之后,会被自动删除。

4. redo log和bin log对比

1)redo log是属于innoDB层面,binlog属于MySQL Server层面的

2)redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑

3)redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖

4)binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用

5. redo log buffer

一块内存,写redo log时,先修改内存redo log buffer,再【按时】,或者当【事务提交】时写入磁盘

问题:redo log buffer的内容未刷到磁盘,会丢吗

如果事务执行期间MySQL发生异常重启,那这部分日志就丢了,但是由于事务并没有提交,所以这时日志丢了也不会有损失

问题:事务还没提交的时候,redo log buffer中的部分日志可能被持久化到磁盘呢

1)后台线程每秒一次的轮询操作

2)redo log buffer占用的空间即将达到一定阈值时,后台线程会主动写盘

3)并行的事务提交的时候,顺带将这个事务的redo log buffer持久化到磁盘

6. MySQL 的“双 1”配置

1)sync_binlog设置成1

0表示每次提交事务都只write,不fsync(write指把日志写入到文件系统的page cache,并没有持久化到磁盘)

1表示每次提交事务都会执行fsync

N(N>1) 时表示每次提交事务都write,但累积N个事务后才fsync

2)innodb_flush_log_at_trx_commit设置成 1

0表示每秒触发一次缓冲日志写磁盘操作,写入效率最高,数据安全最低。

1表示立即将redo log Buffer写入redo log file,数据安全最高,性能受到影响(最安全,推荐)

2表示将redo log Buffer刷新到OS Cache(内核缓冲区Page Cache),然后依托OS每秒刷新一次写入redo log file

7. 两阶段提交

redo log先prepare完成,再写binlog,最后才进入redo log commit阶段

预提交:当一个事务执行UPDATE、INSERT或DELETE等修改操作时,MySQL将这些操作记录到redo log缓冲区中,并将该事务状态设置为“prepare”状态

1)时刻A MySQL重启

由于此时binlog还没写,redo log也还没提交,所以崩溃恢复的时候,这个事务会回滚

2)时刻B MySQL重启

如果redo log里面的事务是完整的,也就是已经有了commit标识,则直接提交;

如果redo log里面的事务只有完整的prepare,则判断对应的事务binlog是否存在并完整:

1)如果是,则提交事务

2)否则,回滚事务

 

 

 

 

 

 

 

五、一条更新语句执行的顺序

update T set c=c+1 where ID=2;

a.执行器先找引擎取ID=2这一行,ID是主键,如果这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。

b.执行器拿到引擎给的行数据,把这个值加上1,比如原来是N,现在就是N+1,得到新的一行数据,再调用引擎接口写入这行新数据。

c.引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。

d.执行器生成这个操作的binlog,并把binlog写入磁盘。

e.执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更新完成。

 

六、

 

七、在两阶段提交的不同时刻MySQL出现异常,重启后会出现什么情况

假设在redo log处于prepare阶段,写binlog之前为时刻A,在写binlog之后,redo log处于commit阶段之前为时刻B

如果在时刻A发生crash,由于binlog还没有写,redo log也还没有提交,所以崩溃恢复的时候,这个事务会回滚

如果在时刻B发生crash,这时候binlog写完,redo log还没有commit,那么在崩溃恢复时MySQL会做以下判断规则:

1、如果redo log里面的事务是完整的,也就是已经有了commit标识,则直接提交;

2、如果redo log里面的事务只有完整的prepare,则判断对应的事务binlog是否存在并完整:

如果是,则提交事务;否则,回滚事务。

 

标签:binlog,事务,log,提交,MySQL,日志,redo
From: https://www.cnblogs.com/xiaojuzi1024/p/17978598

相关文章

  • django使用redis集群、连接池、MySQL连接池
    redis的相关设置CACHES={"default":{"BACKEND":"django_redis.cache.RedisCache","LOCATION":["redis://127.0.0.1:6379/1","redis://127.0.0.1:6380/1",#...],"OPTIONS":{"CLIENT_......
  • mysql 修改密码
    1、找到根目录登录msql   1)以本机为例,mysql安装目录为:usr/localhost/mysql5.7   2)cd  usr/loclahost/mysql5.7/bin    3)登录    4)查看MySQL用户2、 在mysql5.7版本中存放密码字段为authentication_string,再msyql库中#进入mysql库中mysql>......
  • HDP 相关日志位置
      1.HIVESERVER2的日志:/var/log/hive-rwxrwxrwx1hivehadoop4791月1418:20hive.err-rwxrwxrwx1hivehadoop24381月1320:27hivemetastore-gc-2024-01-13_20-27-25.log.0.current-rwxrwxrwx1hivehadoop1032641月1321:47hivemetastor......
  • 蓝桥杯准备---练习日志
    2024-01-17利用Cubemx配置usart中Asyn...和Syn....的意思是什么? 使用串口时报错如下------解决办法:添加st官方提供的串口驱动文件 修改底层printf内部的fputs代码---实现printf函数通过串口输出,需要利用LIB什么的......我猜测这个函数是向某个文件流中写......
  • 如何使用mysql.server制作sysytemctl服务
    mysql.server是MySQL的一个启动脚本,通常用于启动、停止、重启和管理MySQL服务。如果你想使用systemctl来管理MySQL服务,你需要创建一个systemd服务文件,因为systemctl是systemd的命令行工具。下面是如何创建和使用systemd服务文件来管理MySQL服务的步骤:首先找......
  • 在Java中连接8.0版本以上的Mysql数据库
    一.连接数据库在使用Java连接8.0版本以上的数据库时,可以按照如下步骤:下载需要的包,本次教程中使用的是下面这个版本。该驱动网上有许多资源,可根据自己的需求下载。建立与数据库的连接单元在合适的包下新建"DButil.java"文件并输入如下代码:importjava.sql.Connecti......
  • 在 SpringBoot 项目中使用 MDC 实现日志 traceId 的统一
    前言在项目中,对于每一次请求,我们都需要一个traceId将整个请求链路串联起来,这样就会很方便我们根据日志排查问题。但是如果每次打印日志都需要手动传递traceId参数,也会很麻烦,MDC就是为了解决这个场景而使用的。注:这里我们使用slf4j+logbacklogback配置logback.xml......
  • Java每7天日志自动清理
    实现Java每7天日志自动清理作为一名经验丰富的开发者,我很高兴能够教会你如何实现Java每7天日志自动清理的功能。在开始之前,让我们先来了解一下整个流程,然后再逐步进行实现。整体流程如下所示:journeytitleJava每7天日志自动清理流程section步骤清理日志文件-......
  • 使用 Canal 实时从 MySql 向其它库同步数据
    目前绝大多数项目还是采用mysql作为数据存储,对于用户访问量较高的网站来说,mysql读写性能有限,我们通常会把mysql中的数据实时同步到Redis、mongodb、elasticsearch等中间件中,应对高并发访问场景,减轻mysql压力,防止数据库宕机。在项目开发中,为了不会原有代码进行侵入,采用c......
  • 利用aop、拦截器HandlerInterceptor来实现接口限流,日志收集
    前言:aop是面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。拦截器是web请求中一个请求周期中的一环就实现接口限流这个需求来说,用aop和HandlerInterceptor都可以来实现,就是在调用接口之前做一些约束而已。aop+自定义注解+Semaphore实现接口限流自......