赞
踩
事务是一个最小的,不可在分割的工作单元,通常一个事务对应一个完整的业务,一个完整的业务需要批量的DML(insert,update,delete)语句共同联合完成。
一致性、持久性、原子性、隔离性
innoDB引擎中定义了四种隔离级别,级别越高,事务的隔离性越好,但是性能越低。
- 脏读:事务A读取到了事务B更新了但是未提交的数据,然后事务B由于某种错误发生回滚,那么事务A读取到的就是脏数据。----读取未提交的数据!
- 不可重复读:指在数据库访问时,一个事务在前后两次相同的访问中却读到了不同的数据内容。---- 前后多次读取,数据内容不一致!
- 幻读:指的是事务A在查询完记录总数后,事务B执行了新增数据的操作,事务A再次查询记录总数,发现两次查询的结果不一致,平白无故的多了几条记录,这种现象称为幻读。---- 前后多次读取,数据内容不一致!
不可重复读和幻读的差别在哪里呢?----- 本质是一样的,两者都表现为两次读取的结果不一致。但是不可重复读指的是两次读取同一条记录的值不同,而幻读指的是两次读取的记录数量不同。
4、mysql中的锁分类
当前读:即读取当前最新提交的数据,本质上是基于锁的并发读操作。
快照读: 读取某一个快照建立时的数据(也就是某一个时间点的数据),也称作一致性读。快照读主要体现在select操作时,不同隔离级别下,行为的不同:
MVCC多版本并发控制是一个概念:“维持一个数据的多个版本,使得读写操作没有冲突”,快照读其实就是MVCC实现的一种方式,是一种非阻塞读。相对的,当前读就是悲观锁的一种具体实现。
数据库并发场景有三种:
读-读: 不存在任何问题,也不需要并发控制
读-写: 有线程安全问题,可能造成事务的隔离性问题,如脏读,幻读,不可重复读
写-写: 有线程安全问题,可能会存在更新丢失的问题。
MVCC带来的好处:
MVCC是一种用来解决读-写冲突的 无锁并发控制,简而言之,是因为人们不满意采用悲观锁这样性能不佳的形式去解决读-写冲突问题,而提出的解决方案。
MVCC为事务分配单向增长的时间戳,为每个修改保存一个版本,版本和事务的时间戳相关联,读操作只读该事务开始前的数据库快照,因此MVCC可以解决:
1、并发读写数据库时,在读操作的时候不用阻塞写操作,写操作也不会阻塞读操作,提高了并发读写的性能
2、可以解决脏读,幻读,不可重复读等事务隔离问题,但是无法解决更新丢失问题。
数据库表字段除了我们自定义的字段外,数据库还隐式的定义了DB_TRX_ID
、 DB_ROLL_PTR
、 DB_ROW_ID
等字段
DB_TRX_ID:
6byte,最近修改(插入和更新)的事务的id
DB_ROLL_PTR:7
byte,回滚指针,指向这条记录的上一个版本
DB_ROW_ID
:6byte,隐藏的自增ID,如果数据表没有主键,innoDB会自动以DB_ROW_ID创建一个聚簇索引。
undo log日志主要分为两种:
对MVCC有帮助的实际是update undo log,其实就是一个版本链。不同事务或者相同事务对同一条记录的修改,会导致该记录的undo log成为一个记录版本的线性表(链表),链首的位置就是最新的旧记录(记录最近一次被修改之前的数据),链尾就是最早的旧记录。下面介绍一下流程:
1、数据库中本来存在一条记录
2、现在开启了一个事务1,对这个记录的name进行修改操作:
3、现在又来了一个事务2,想修改同一行数据,将age变成30
read view就是事务进行快照读操作的时候产生的一个读视图。在一个事务执行到快照读的那一个时刻,会生成数据库系统当前的一个快照,记录并且维护系统当前活跃事务的id(每个事务开启的时候都会被分配一个id,这个id是递增的,因此id越大,代表事务越新)
read view 读视图 的三个属性
read view 遵循一个可见性算法:当一个事务读取某条数据的时候,会根据DB_TRX_ID(也就是undo log日志中链首的id在坐标轴上的位置来进行可见性判断):
1、DB_TRX_ID < up_limit_id,则当前事务可以看到DB_TRX_ID的记录,否则进入下一个判断。
2、DB_TRX_ID >= low_limit_id, 则说明DB_TRX_ID所在的记录提交是在readview生成之后,当前事务肯定是不可见的。
3、DB_TRX_ID是否在活跃事务trx_list之中,如果在,说明readview生成时刻,DB_TRX_ID还未提交,因此 无法读到DB_TRX_ID修改的数据。如果不在,说明DB_TRX_ID在readview生产之前就已经提交了,那么修改的结果是可见的。
解释一下第3点:
当前事务2开始select的时候,几个参数的值为:
trx_list --- > 1、2、3
low_limit_id ---> 5
up_limit_id ---> 1
DB_TRX_ID ---> 4
对应上述第3点的后半段,因此事务2是可以看到事务4修改的值
当前事务2开始select的时候,几个参数的值为:
trx_list --- > 1、2、4
low_limit_id ---> 5
up_limit_id ---> 1
DB_TRX_ID ---> 3 (假设事务3是当前时刻最后一次提交的)
对应上述第3点的前半段,因此事务2无法看到事务4修改的值
在上述介绍中,发现:事务的快照读的结果是十分依赖该事务首次出现快照读的时机,它决定了该事务后续快照读结果的能力(如事务2首次读 在事务4 提交修改之前和之后的差异)。这个其实是在mysql默认的RR级别下才有的现象。
总结: RR级别同一个事务第一次快照读才会创建read view(后续都用这个一个read view才会保证每次读的到数据都是一样的,即可重复读),而RC级别每次快照读都会创建一个readview。
insert或者update,都会被阻塞。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。