数据库的事务

基本特性:

原子性:

事务最为最小单位,事务内所有操作,要么一起成功,要么一起失败

一致性:

指数据库总是从一个一致性的状态转换到另外一个一致性的状态,比如A装在B100,假设A只有90,支付前我们数据库里的数据都是符合约束的,但是如果事务执行成果了,我们的数据库就破坏了约束,因此事务不能成功,这里我们说事务提供了一致性的保证,或者说,A给B转账100,A必须减少100,而不是80、90,同时B也必须增加100,不能增加80、90

隔离性:

事务与事务之间相互隔离,互不影响(存在读已提交,读未提交,可重复度,串行化十个隔离级别)

持久性:

事务一旦提交,将永久保存在数据库中。

如何保证ACID

A:原子性有undo log日志保证,它记录了需要回滚的日志信息,事物回滚时撤销已经执行成功的sql
C:一致性由其他三大特性保证、程序代码要保证业务上的一致性
I:隔离性有MVVC来保证
D:持久性由内存+redo log 来保证,MySQL修改数据同时在内存和redo log记录这次操作,宕机的时候可以从redo log恢复

InnoDB redo log 写盘,InnoDB事物进入prepare状态,
如果前面prepare成功,binlog写盘,再据需将事务日志持久化到binlog,如果持久化成功,那么InnoDB事务则进入到commit状态(在redo log里面写一个commit记录)。

redo log的刷盘会在系统空闲的时候进行。

binlog记录日志的三种格式:

1、Row level
记录的方式是行,即如果批量修改数据,记录的不是批量修改的sql语句事件,而是每条记录更改的SQL语句,因此ROW模式的binlog日志文件会变得很重。
记录非常详细,但是日志量很大,IO占用多,性能较低
2、Statement Level
记录每一条修改数据的sql语句(批量修改时,记录的不是单条语句,而是批量修改的SQL语句事件)。
这样大大减少了日志量,节省磁盘IO,提高性能
3、Mixed
在这种模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。

如何选择binlog模式

1、如果生成中使用的MySQL的特殊功能相对较少(存储过程、触发器、函数)。默认选择的语句模式,Statement level
2、如果生成中使用MySQL的特殊功能较多,可以选择Mixed模式
3、如果生产中使用MySQL的特殊功能较多,又希望数据最大化一致,此时最好Row level模式;但是要注意,该模式的binlog日志量非常的大

MVCC

多版本并发控制:读取数据时通过一种类似快照的方式将数据保存下来,这样读锁和写锁就不冲突了,不同的事务session会看到自己特定版本的数据,版本链
MVCC只在读已提交和可重复读两个隔离级别下工作。其他两个隔离级别和MVCC不兼容,因为读未提交总是读取最新的数据行,而不是符合当前事务版本的数据,而串行化则会对所读的行都加锁。

聚族索引记录中有两个必要的隐藏列:
trx_id(隐藏的事务ID):用来存储每次对某条聚族索引记录进行修改的时候的事务ID
roll_polnter(指向上一个版本的指针):每次对那条聚族索引记录修改的时候,都会把老版本写入undo log中,这个roll_polnter就是存了一个指针,它指向这条聚族索引上记录的上个版本的位置,通过他来获取得到上一个版本的记录信息(插入操作的undo log没有这个属性,因为它没有老版本)

读已提交和可重复度的区别就在于他们生成的readView的策略不同

开启事务的时候,首先会创建一个ReadView,ReadView维护当前活动的事务id,即未提交的事务ID,排序生成一个数组,获取数据组的事务ID,对比ReadView;
如果事务ID比ReadView都小,可以访问(意味着事务已经提交)
如果事务ID比ReadView都大,或者就在ReadView中,不可以访问,获取roll_pointer,取上一个版本重新对比;
读已提交的事务,在每次查询开始的时候都生成一个新的ReadView,而刻重复读则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView

隔离级别

读未提交:

读取到令一个事务未提交的数据(脏读)

读已提交:

读取已提交事务,解决了脏读的问题,但是还有可能出现不可重复读(在A的同一个事务中,B事务进行更新、新增操作,A事务在B提交前后两次读取,读取同一条数据时,B事务提交前和B事务提交后得到的数据不同)的问题,读已提交readView再每次查询的时候都会重新生成;

可重复的:

解决了不可重复读的问题,readView不会重新生成,但是可能会出现幻读的现象,(幻读就是:一个事务在前后两次查询同一个范围的时候、后一次查询看到了前一次查询未看到的行)

串行化:

每个事务独占锁,进行当前事务的时候其他事务不能进行操作

你可能感兴趣的:(数据库,mysql)