mysql 8.0 学习笔记07 锁和事务
概念介绍:
事务:
ACID 特性
原子性(Atomicity) |
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚 |
一致性(Consistency) |
事务只能以允许的方式改变其受影响的数据 |
隔离性(Isolation) |
并发事务,不能导致数据库处于不一致的状态。 |
持久性(Durability) |
无论数据库和系统是否发生故障,数据都会永久保留在磁盘上,并且不会丢失 |
只有innodb支持事务。
隔离级别:
事务隔离级别(只说常用的两种) |
默认配置 |
Read-Committed 不可重复读 |
oracle、pg、sqlserver 等 |
Repeatable-Read 可重复读 |
mysql默认 |
脏读 |
读到其他事务未提交的数据; |
不可重复读 |
针对数据修改Update造成的不一致,称为不可重复读 |
幻读 |
针对数据插入和删除等造成的不一致 |
锁:
innodb 行锁是通过给索引项加锁实现的。
如果没有索引,会通过隐藏的聚簇索引来对记录加锁。
如果不通过索引条件检索数据,那么innodb将对表中所有的数据加锁,实际效果跟表锁一样。
索引加锁过程:
首先对二级索引加锁,然后还需要关联到主键索引,进行加锁。
锁队列:
当排它锁在队列中时,所有后续的共享锁也将被阻塞并保留在队列中。
锁的兼容性:
意向锁之间,完全兼容;
S锁之间,互相兼容。
X锁,相互排斥、完全排斥。
特别说明:flush table with read lock;
等待表中所有操作完成,也将阻止该表上的所有操作。
为了备份一致性,所有备份方法都使用flush tables with read lock;然而,如果表上存在长时间运行的事务,这种做法可能会带来危险。
MVCC——简称multiversion concurrency control,也就是多版本并发控制,是个很基本的概念。MVCC的作用是让事务在并行发生时,在一定隔离级别前提下,可以保证在某个事务中能实现一致性读,也就是该事务启动时根据某个条件读取到的数据,直到事务结束时,再次执行相同条件,还是读到同一份数据,不会发生变化(不会看到被其他并行事务修改的数据);
read view——InnoDB MVCC使用的内部快照的意思。在不同的隔离级别下,事务启动时(有些情况下,可能是SQL语句开始时)看到的数据快照版本可能也不同。在上面介绍的几个隔离级别下会用到 read view;
快照读——就是所谓的根据read view去获取信息和数据,不会加任何的锁;
当前读——前读会获取得到所有已经提交数据,按照逻辑上来讲的话,在一个事务中第一次当前读和第二次当前读的中间有新的事务进行DML操作,这个时候俩次当前读的结果应该是不一致的,但是实际的情况却是在当前读的这个事务还没提交之前,所有针对当前读的数据修改和插入都会被阻塞,主要是因为next-key lock解决了当前读可能会发生幻读的情况。next-key lock当使用主键索引进行当前读的时候,会降级为record lock(行锁)。
innodb 为实现MVCC,UNDO 回滚,所有行 增加了三个内部属性列
DB_TRX_ID: 记录每行最近修改它的事务ID;
DB_ROLL_PTR: 指向回滚段UNDO日志的指针;
DB_ROW_ID: 写入数据时,自动维护的自增列。
READ COMMITTED和REPEATABLE READ隔离级别是利用consistent read view(一致读视图)方式支持的。所谓的consistent read view就是在某一时刻给事务系统trx_sys打snapshot(快照),把当时的trx_sys状态(包括活跃读写事务数组)记下来,之后的所有读操作根据其事务ID(即trx_id)与snapshot中trx_sys的状态做比较,以此判断read view对事务的可见性。
REPEATABLE READ隔离级别(除了GAP锁之外)和READ COMMITTED隔离级别的差别是创建snapshot时机不同。
REPEATABLE READ隔离级别是在事务开始时刻,确切的说是第一个读操作创建read view的时候,READ COMMITTED隔离级别是在语句开始时刻创建read view的。
因此:REPEATABLE READ隔离级别下面一个事务的SELECT操作只会获取一个read view,但是READ COMMITTED隔离级别下一个事务是可以获取多个read view的。