MYSQL 事务
-
ACID属性
- 原子性(Atomicity)
- 事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行
- 一致性(Consistent)
- 在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,
- 以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的
- 隔离性(Isolation)
- 数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。
- 这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然
- 持久性(Durable)
- 事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持
- 原子性(Atomicity)
-
并发事务处理带来的问题
- 更新丢失(Lost Update)
- 两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,
- 就会发生丢失更新问题–最后的更新覆盖了由其他事务所做的更新
- 脏读(Dirty Reads)
- 事务A读取到了事务B已经修改但尚未提交的数据,还在这个数据基础上做了操作。
- 此时,如果B事务回滚,A读取的数据无效,不符合一致性要求
- 不可重读(Non-Repeatable Reads)
- 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”。一句话:事务A读取到了事务B已经提交的修改数据,不符合隔离性
- 幻读(Phantom Reads)
- 个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,
- 这种现象就称为“幻读”
- 脏读是事务B里面修改了数据,幻读是事务B里面新增了数据
- 更新丢失(Lost Update)
-
事务隔离级别
- 分类
- 读未提交(Read uncommitted)
- 脏读/不可重复读/幻读
- 读已提交(Read committed)
- 不可重复读/幻读
- 可串行化(Serializable)
- 脏读/不可重复读/幻读都不可能
- mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,
- 这种隔离级别并发性极低,开发中很少会用到
- 脏读/不可重复读/幻读都不可能
- 可重复读(Repeatable read)
- 幻读
- 可重复读的隔离级别下使用了MVCC机制,select操作不会更新版本号,是快照读(历史版本)
- insert、update和delete会更新版本号,是当前读(当前版本)
- 要避免幻读可以用间隙锁在Session _1下面执行update account set name ='zhuge'where id> 10 and id<= 20;,则其他Session没法插入这个范围内的数据
- 幻读
- 读未提交(Read uncommitted)
- 查看隔离级别
- show variables like 'transaction_isolation';
- select @@transaction_isolation;
- 默认的事务隔离级别(Repeatable read)
- 分类
-
MVCC(多版本并发控制)
- 假设同一份数据,既有读事务访问,又有写事务操作,实际上,写事务会新建一个新的数据版本,而读事务访问的是旧的数据版本,直到写事务提交,读事务才会访问到这个新的数据版本
- 实现方式
- 数据记录的多个版本同时保存在数据库
- 使用undo_log动态构造(mysql的innodb使用该实现)
- 实现原理
- 在每一行有隐藏列,当前行的创建事务id,删除事务id, 上一个版本指针(undo_log, 同一条记录可能会存在多个版本, 呈链表结构)
- 读取每一行的时候
- 判断记录是否被修改
- 当前行的创建事务id > 当前事务id, 说明记录在事务开启前已被修改了, 需要从undo_log回滚
- 判断记录是否被删除
- 当前行的删除事务id < 当前事务id, 说明记录在事务开启前已被删除, 则过滤
- 判断记录是否被修改
各位看官大佬,不足之处,多多批评指正,不胜感激!

浙公网安备 33010602011771号