一、事务的特性(ACID),原子性,一致性,隔离性,持久性;
二、Mysql的事务隔离级别
1、读未已提交(READ UNCOMMITTED):
一个事务可以读取到未提交的数据(比如只进行了更新操作),产生脏读,幻度。
2、读已提交(READ COMMITTED):
事务读取到已经提交的数据,多次select,查询结果不一致,产生幻度。
3、可重复读(REPEATABLE READ) :
一个事务中多次读取数据相同,可能产生幻读,但是mysql的可重复读解决了幻读的问题,事务读取可以分为:快照读使用与select 语句,比如:select id from user where id = 1 (MVCC:READVIEW 和 版本链解决)、当前读,比如:select id from user where id = 1 for update (一个事务内读取数据,间隙锁),可以参考一下链接加深理解:https://blog.csdn.net/qq_40918324/article/details/104617714。
4、串行化(SERIALIZABLE):
三、1、 什么是版本链:
在innoDB存储引擎的表,有三个隐藏列分别是:row_id,trx_id,roll_pointer,其中row_id不是必要的,如果有主键索引,则列号不一定存在。
trx_id:记录当前事务的事务号。
roll_pointer:指向前一个事务号,(通过指针找到修改前的记录)。
2、ReadView:
① 对于读已提交和可重复读,需要使用上述的版本链,核心问题:找到哪个事务是正确的,可见的。那么怎么判断哪个事务版本是可用的呢,就需要ReadView了,我发现其实很多人都在说mvcc但是却不知道readView,真的是很奇怪。
② ReadView 主要由四部分组成:
1、m_ids:记录当前活跃的所有事务,相当于一个数组,[1,2,3,4]
2、min_trx_id: 记录当前活跃事务中最小的事务号。
3、max_trx_id:记录下一个应该开启的事务的事务号,事务号是递增的,其实就是时间戳。
4、creator_trx_id:表示生成该ReadView的事务号。
④ 对于读已提交和可重复读,在生成ReadView的规则不同,导致了他们读取数据时候的区别:
1、读已提交:每次执行select的时候都会生成一个readView,记录当前活跃的事务id。所以他可以读取到最新的别提交过的数据。
2、可重读度:他只会在第一次执行select 语句的时候生成ReadView,所以多次执行ReadView相同所以查询数据相同。
四、mysql innoDB的行锁与表锁
一、行锁:
1、行锁分为: ① LOCK_REC_NOT_GAP:单个行记录上的锁。
② LOCK_GAP:间隙锁,只会锁住查询数据之间的间隙。
③ NEXT_KEY_LOCK:结合单行锁和间隙锁的锁。
2、对于读已提交,不存在间隙锁,只会对表中查询出来的数据加锁。
3、对于可重读度,对于主键索引和二级索引不会加间隙锁。对于普通索引和没有索引的列,会对查询出来的数据的间隙加锁(可能会造成死锁)。
4、这里的锁对于二级索引,首先会对索引字段加锁,再下来同时会对,索引页中的主键id进行加锁,为什么会加两次锁?
① 当查询数据有二级索引列时,直接判断加锁快速返回。
② 当当前查询没有二级索引列,但是时主键索引对应的数据时,保证数据被加锁。