mysql innodb存储引擎学习

事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)

事务四大特征(ACID)

原子性(A)原子性就是不可拆分的特性,要么全部成功然后提交(commit),要么全部失败然后回滚(rollback)。MySQL通过Redo/undo Log重做日志实现了原子性,在将执行SQL语句时,会先写入 log buffer,再执行SQL语句,若SQL语句执行出错就会根据undo log buffer中的记录来执行回滚操作,由此拥有原子性。

一致性(C) 一致性指事务将数据库从一种状态转变为下一种一致的状态。比如有一个字段name有唯一索引约束,那么在事务前后都不能有重复的name出现违反唯一索引约束,否则回滚。由原子性,隔离性,持久性共同保证。

隔离性(I):事务A和事务B之间具有隔离性。通过锁来实现。

持久性(D):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中)。一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。具体实现原理就是在事务commit之前会将,redo log buffer中的数据持久化到硬盘中的redo log file,这样在commit的时候,硬盘中已经有了我们修改或新增的数据,由此做到持久化。

隔离性有隔离级别

读未提交:read uncommitted

  事务中的修改,即使没有提交,其他事务也可以看得到。

读已提交:read committed

  大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,该级别适用于大多数系统

重复读repeatable read

  保证了一个事务不会读到另一个并行事务已提交的数据。

串行化:serializable

  严格的级别,事务串行执行,资源消耗最大

脏读当前事务到了别的事务回滚前的脏数据

不可重复读当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配(updatedelete)。通过mvcc解决

当前事务读第一次取到的数据没有对应记录a,但是插入时却因为其他并行事务插入并提交记录a导致冲突(insert)。通过Next-Key Locks解决

Next-Key Locks:在索引记录上加锁,并且在索引记录之前的间隙加锁(左开右闭)

在可重复读隔离级别下,对于普通select语句,通过mvcc读取快照,对于select...for update/lock in share mode,则通过Next-Key Locks保证不出现幻读。

(当where条件为唯一主键且存在记录时,临键锁优化为行锁,当不存在时,为临键锁;

where条件为普通索引时为临键锁)

MVCC原理:

通过事务版本号进行mvcc,系统维护一个系统版本号,进行插入操作的时候就把插入记录的系统列事务id设置为当前系统版本号;对于删除操作,则是将记录标记为delete mark,并将事务id改为当前系统版本号;对于更新操作,则是同时保持旧记录和新纪录;对于查询操作则是根据当前系统版本号和查询行的事务id来判断记录是否可读。

决定记录是否可读的规则是由read view决定的,当隔离级别为可重复读时,每个事务开始时都会将当前系统所有的活跃事务拷贝到一个列表中(read view);当隔离级别为读取已提交时,在每个事务的每个语句开始时都会将所有活跃事务拷贝到read view中。

事务提交过程:

  1. start transaction;

  2. 记录 A=1 undo log;

  3. update A = 2

  4. 记录 A=2 redo log

  5. 记录 B=3 undo log

  6. update B = 4

  7. 记录B = 4 redo log

  8. redo log刷新到磁盘

  9. commit 

1-8的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务提交,因为此时redo log已经持久化。若在9之后系统宕机,内存映射中变更的数据还来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘。

recovery

1.启动开始时检测是否发生崩溃

2.定位到最近的一个checkpoint

3.定位在这个checkpointflush到磁盘的数据页,检查checksum。如果不正确,说明这个页在上次写入是不完整的,从doublewrite buffer里把正确的页读出来,更新到buffer中的页

4.分析redo log,标识出未提交事务

5.顺序执行redo

6.rollback未提交的事务

两阶段提交:

两阶段提交:当事务提交时,innodb存储引擎会先做一个prepare操作,将事务的xid写入,接着binlog日志的写入。如果在innodb存储引擎提交前,mysql数据库宕机了,那么mysql数据库在重启后会先检查准备的xid事务是否已经提交,若没有,则在存储引擎层在进行一次提交操作。

第一阶段:InnoDB prepare,持有prepare_commit_mutex,并且write/sync redo log; 将回滚段设置为Prepared状态,binlog不作任何操作;

第二阶段:包含两步,1> write/sync Binlog2> InnoDB commit (写入COMMIT标记后释放prepare_commit_mutex)

binlog 的写入与否作为事务提交成功与否的标志,innodb commit标志并不是事务成功与否的标志。

事务崩溃恢复过程如下:

1> 崩溃恢复时,扫描最后一个Binlog文件,提取其中的xid; 

2> InnoDB维持了状态为Prepare的事务链表,将这些事务的xidBinlog中记录的xid做比较,如果在Binlog中存在,则提交,否则回滚事务。

通过这种方式,可以让InnoDBBinlog中的事务状态保持一致。

如果在写入innodb commit标志时崩溃,则恢复时,会重新对commit标志进行写入;

prepare阶段崩溃,则会回滚,在write/sync binlog阶段崩溃,也会回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值