7-MySQL原理-事务底层实现

240 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Binlog原理

二进制日志(binlog)

binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。

binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但你可以通过查询通用日志来查看MySQL执行过的所有语句。

二进制日志包括两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句)语句事件。

事务日志

innodb事务日志包括redo log和undo log。

undo log指事务开始之前, 在操作任何数据之前,首先将需操作的数据备份到一个地方

redo log指事务中操作的任何数据,将最新的数据备份到一个地方

事务日志的目的:实例或者介质失败,事务日志文件就能派上用场。

1.redo log不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo 中。具体 的落盘策略可以进行配置 。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。RedoLog是为了实现事务的持久性而出现的产物 在这里插入图片描述

2.undo log用来回滚行记录到某个版本。事务未提交之前,Undo保存了未提交之前的版本数据,Undo中的数据可作为数据旧版本快照供其他并发事务进行快照读。是为了实现事务的原子性而出现的产物,在Mysql innodb存储引擎中用来实现多版本并发控制

Redolog知识补充

指定Redo log 记录在{datadir}/ib_logfile1&ib_logfile2 可通过innodb_log_group_home_dir 配置指定 目录存储

一旦事务成功提交且数据持久化落盘之后,此时Redo log中的对应事务数据记录就失去了意义,所 以Redo log的写入是日志文件循环写入的

指定Redo log日志文件组中的数量 innodb_log_files_in_group 默认为2

指定Redo log每一个日志文件最大存储量innodb_log_file_size 默认48

指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默认16Redo buffer 持久化Redo log的策略, Innodb_flush_log_at_trx_commit:

取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丢失一秒的事务数据]

取值 1 默认值,每次事务提交执行Redo buffer --> Redo log OS cache -->flush cache to dis[最安全,性能最差的方式]

取值 2 每次事务提交执行Redo buffer --> Redo log OS cache 再每一秒执行 ->flush cache tdisk操作

快照读和当前读

快照读:SQL读取的数据是快照版本,也就是历史版本,普通的SELECT就是快照读 innodb快照读,数据的读取将由 cache(原本数据) + undo(事务修改过的数据) 两部分组成

当前读:SQL读取的数据是最新版本。通过锁机制来保证读取的数据无法通过其他事务进行修改 UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE都是 当前读

Undo + Redo事务的简化过程

假设有A、B两个数据,值分别为1,2,开始一个事务,事务的操作内容为:把1修改为3,2修改为4,那么实际的记录如下(简化):

A.事务开始.
B.记录A=1到undo log.
C.修改A=3.
D.记录A=3到redo log.
E.记录B=2到undo log.
F.修改B=4.
G.记录B=4到redo log.
H.将redo log写入磁盘。
I.事务提交

二进制日志处理事务和非事务性语句的区别

在事务性语句(update)执行过程中,服务器将会进行额外的处理,在服务器执行时多个事务是并行执行的,为了把他们的记录在一起,需要引入事务日志的概念。在事务完成被提交的时候一同刷新到二进制日志。对于非事务性语句(insert,delete)的处理。遵循以下3条规则:

1)如果非事务性语句被标记为事务性,那么将被写入重做日志。

2)如果没有标记为事务性语句,而且重做日志中没有,那么直接写入二进制日志。

3)如果没有标记为事务性的,但是重做日志中有,那么写入重做日志。

注意如果在一个事务中有非事务性语句,那么将会利用规则2,优先将该影响非事务表语句直接写入二进制日志。