简单来讲事务是为了保证一组数据库操作要么全部成功,要么全部失败,将一个或多个操作尽可能编程一个原子操作,隔离的引入就是为了克服多个事务同时运行,并且同时处理相同的表或者行时,为了保持数据一致性,不产生相互干扰而使用的措施。
-
首先考虑可能出现的问题
脏读、不可重复读、幻读
**脏读:**读到另一个事务中正在处理中的数据
**不可重复读:**就是在事务进行的不同阶段对数据进行读取会读取到不同的数据
**幻读:**在一个事务中,相同范围内读取到的数据量不同。幻读在“当前读”下才会出现。
幻读是针对insert导致的数据不一致,不可重复读是针对 delete、update导致的数据不一致。 -
解决这种方式的方法就是利用四种隔离级别
读未提交、读提交、可重复读、串行化。这几个隔离级别的消耗是依次增加的
1.读未提交:一个事务修改的数据还未提交就能被其他事务看见
2.读提交:一个事务提交之后变更才能被看见
3.可重复读:一个事务读取到的内容都是在事务开始时的样子
4.串行化:写会加写锁,读会加读锁,当出现读写锁冲突的时候就会等待事务完成后再继续执行。 -
这些隔离等级是结合mvcc多版本并发控制系统和锁来实现的。
虽然会有多个事务并行处理的感觉,但是如果出现了x锁的冲突就会出现阻塞,而通过mvcc多版本并发控制就可以实现“你已经改过了”我看见的确实以前的数据的错觉
当数据修改时,innodb会记录一个undolog,undolog 记录的内容是反操作用来回滚,比如操作给insert undolog就记录delete。在进行行修改操作的时候,会根据顺序给每个事务一个id号,然后修改的每个行都会记录这个id号:row trx_id ,在事务启动的时候会拍一个快照,即一致性视图。当进入事务的时候,本事务就会记录当前正在活跃的事务,即开启的但是没有提交的事务。对于一致性读来说,这个活跃的事务都是不可读的,当本事务去读取行的时候就会根据id号来判断,如果这个id号大于本事务的id号,就根据undolog回滚到之前的数据情况返回数据, 而写的时候都是执行当前读,因为更改是累积的不会进行回滚。在这里插入代码片