1、MySQL事务了解
数据库事务是指一组sql语句组成的数据库逻辑处理单元,在这组sql操作中,要么全部成功要么全部失败
举例:经典的例子就是转账,事务A要进行转账,那么转出的账号要扣,转入的账号要加钱,这两个操作就要同时执行成功或执行失败,为了确保事务的一致性。
2、事务的特性(ACID)
Mysql事务的四大特性主要包括:原子性(Atomicity)、一致性(Consistent)、隔离性(Isalotion)、持久性(Durable),简称ACID
原子性是指事务的原子性操作,对数据的修改要么全执行成功,要么全执行失败,实现事务的原子性是基于日志的Redo/Undo机制。
一致性是指执行事务前后的状态要一致,可以理解为数据的一致性
隔离性侧重于事物之间的相互隔离,不受影响,一个与事物之间的隔离级别有密切关系。
持久性是指在一个事务提交后,这个事物的状态会被持久化到数据库中,也就是事务的提交。
在我的理解中,原子性,隔离性,持久性,都是为了保障一致性而存在的,一致性才是最终的目的。
3、事务回滚
当一个事务执行过程中发生了任何异常、错误则重新回到最先未开始执行的过程(比如A向B转100元A-100,但是在进行B+100的时候出现了异常错误,就需要回滚到该交易还未执行的时候)
4、事务提交
当事务执行过程没有出现任何异常,和错误,这是我们就要保存这个事务的修改(A像B转账A-100,B+100之后就需要把这个事务保存,就是提交)
5、事务隔离
由于事务可包含多个操作,在多个客户端并发访问过程,可能会发生一个事务只做了一部分操作,此时另一个事务也开始执行,那么前一个事务的只执行一部分操作的中间状态会给第二个事务造成影响(比如A给B转钱A-10000,B+10000,B查看余额加了10000,结果A发现自己多转了1000,执行了回滚,那么A,B原来的钱是多少现在还是多少,B再看余额就会发现10000没有了)
脏读,一个事务读取到另一个事务未提交的内容(一个事务正在多次修改某条数据还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致)
不可重复读,对数据库中的某个数据,一个事务内多次查询却返回了不同的数据值,这个是由于在查询间隔,另一个事务修改并提交了。
不可重复读和脏读的区别是,脏读读取了另一个事务未提交的数据,而不可重复读是读取了前一个事务已提交的数据
幻读,一个事务前后两次查询同一个范围的时候,后一次查询到了前一个没有查询到的行。如果事务中都是用快照读,那么就不会出现幻读
幻读和不可重复读都是读取了另一条已经提交了的事务(与脏读不同),不可重复读查询的都是同一条数据,而幻读针对的是数据的数量。“脏读”,“不可重复读”,“幻读”,都是数据库读不一致的问题,必须由数据库提供一定的事务隔离机制来解决(在读取数据前,对其加锁,阻止其他事务对数据进行修改)
6、事务隔离级别
Read uncommitted (读未提交):最低级,什么问题也解决不了
Read committed (读已提交):可以避免脏读
Repeatable Read(可重复读):确保事务可以多次从一个字段读取相同的值,在此事务期间,禁止其他事务对此字段进行修改,可以避免脏读和不可重复读。
Serializable (串行化):最严格的事务隔离级别,要求所有事物串行执行,不可并发执行,可以避免脏读,不可重复读,幻读情况的发生
7、事务控制语句
commit:提交
rollback:回滚
start transaction|begin:显示开启一个事务
savepoint identifier:savepoint允许在事务中创建一个保存点,一个事务可以有多个savepoint
release savepoint identifier:删除一个事务的保存点,当没有一个保存点是执行这条语句会抛出异常
rollback to [savepoint] identifier:将事务回滚到标记点,而不是回滚标记点之前的任何工作
set transation :事务的隔离级别
8、事务分类
扁平事务:扁平事务所有操作都处于同一个层次,又开始到结束,期间操作时原子性的,要么执行要么回滚。(扁平事务主要限制是不能提交或者回滚事务的某一部分或分几个步骤提交)
带保存点的扁平事务:(保存点:用来通知系统记住事务当前状态,以便当之后发生错误时,事务能回到保存点当前的状态。)
链事务:再提交事务时释放掉不需要的数据对象,将必要的处理上下文隐式的传送给下一个要开始的事务(可视为保存点模式的另一种实现。带有保存点的扁平事务,当系统发生崩溃时,所有保存点将消失,因为其保存点是易丢失的,而非持久的。这意味着当进行恢复时,事务需要从开始处重新执行,而不能从最近的保存点执行)
嵌套事务:嵌套事务是一个结构层次框架,有一个顶层事务控制着各个层次的事务,顶层事务之下嵌套的事务称之为子事务,其控制这每一个局部的变换。
分布式事务:分布式事务通常是一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。
9、事务的实现
隔离性是通过锁来实现的
redo log 成为重做日志,用来保证原子性和持久性。
undo log用来保证一致性
redo恢复提交事务修改的页操作,而undo回滚记录到某个特点个版本。因此两者记录的内容不同,redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。
redo:当事务提交时,必须先将该事务的重做事务的重做日志写入到重做日志文件种进行持久化,待事务的Commit操作完成才算完成。(为了确保每次日志都写入到重做日志文件,在每次重做日志缓冲写入到重做日志文件后,InnoDB都需要调用一次fsync(同步内存中已修改的文件到磁盘)操作)。
undo:是逻辑日志,因此只是将数据库逻辑的恢复到原来的样子。所有修改都被逻辑的取消了,但数据结构和页本身在回滚之后可能大不相同。因为在多用户并发系统中,一个事务再修改当前一个页中的某几条记录,同时还有别的事务在对同一页另几条记录进行修改,因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务进行的工作。
当InnoDB回滚时,它实际上做的是与之前相反的工作:
对于每个insert,InnoDB会完成一个delete
对于每个delete,InnoDB会完成一个insert
对于每个update,InnoDB会执行一个相反的update,将修改的行放回去
除了回滚操作,undo的另一个作用是mvcc。即当用户读取一行数据时,如该记录已经被其他事务占据,当前事务可以通过undo来读取之前的行版本信息,以实现非锁定读取。