一、事务属性
原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。(针对于操作层面)
一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性。(针对于数据层面)
隔离性(Isolation) :数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
持久性(Durable) :事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
二、并发事务带来的问题
更新丢失或者脏写(Lost Update):当两个事务或者多个事务对同一条数据做更新时,后面提交的数据会覆盖前面的写数据;
脏读(Dirty Reads):事务A读取到了还未提交事务B的数据;
不可重复读(Non-Repeatable Reads):事务A和事务B同时begin时,事务B先提交了,事务A读取到了事务B已提交的数据;
幻读(Phantom Reads):事务A和事务B同时begin时,事务B先提交了,事务A读取到了事务B已提交的新增数据;
三、事务的隔离级别
四、MVCC机制
读已提交和可重复读都是用了MVCC(Multi-Version Concurrency Control)机制;
首先mysql会为每一行数据,多维护trx_id(事务id,一般是自增的)和roll_pointer(回滚指针,上一个版本的指针);再会维护一个undo日志,每当数据有更新时,先把历史版本数据写入undo日志,便于以后回滚;
MVCC机制:在事务开启后,第一个查询语句执行之前,会把当前数据库存在的未提交事务放在一个readView集合中,获取一个当前数据库最大的事务id(max_id);再从readView中选出最小的事务id(min_id);因为事务是自增的;所以当事务开启后,查询到的数据
1.如果trx_id的版本号小于min_id则说明当前这个版本号肯定是在我这个事务开启前已提交的,则是可见的,可以查询出来的数据;
2.如果大于min_id且小于max_id,则需要去看是否在readView集合中,如果在该集合中,则该事务未提交,则是不可见的,需要根据roll_pointer去查找上个版本的数据,直到查找到复核规则的数据;
3.如果是大于max_id,因为事务id是自增的,则该事务肯定是我查询之后才插入的数据,所以该数据是不可见的,则需要查找上个版本数据,直到查找到复核规则的数据;
mysql默认使用可重复读级别,是上述规则;当使用读已提交,区别在于,每次查询语句都会生成一个当前的readView;