MYSQL的事务和锁
一、事务
1、ACID特性
原子性: 一个事务要么全部执行,要么完全不执行 一致性: 事务再开始和结束时,应该始终满足一致性 隔离性: 在事务操作时,其他事务的操作不能影响到当前操作(比如取钱时有人同时转账过来,不应拒绝这样的操作) 持久性: 事务操作的结果是具有持久性的
2、InnoDB的MVCC并发管理
快照读:读取的是数据的可见版本,是数据的历史镜像,这个过程是不加锁的
当前读:读取的是最新的版本,会加上锁,保证其他事务不会再修改这条记录
MVCC在数据声明周期管理里有两个重要的标识,一个是标识数据变化的,一个是标识数据可用状态的
Update:先把当前记录标识为已删除,然后新增一列数据,
Delete:把当前记录标识为已删除
3、事务回滚(InnoDB)
行数据有三个内部属性列
DB_TRX_ID:记录每一行最近一次修改它的事务ID
DB_ROLL_PTR:记录指向回滚段undo日志的指针
DB_ROW_ID:当写入数据时,自动维护的自增列
redo中顺序记录insert、delete、update操作,同时生成undo记录,为逆操作的delete、insert、update
4、事务隔离级别
查看隔离级别的方法: SELECT @@global.tx_isolation SELECT @@session.tx_isolation SELECT @@tx_isolation RC(Read-Committed)不可重复读:Oracle默认隔离级别,事务1未关闭时,事务2修改或插入数据并提交后,事务1查询结果会随着事务2的提交而变化。 RR(Repeatable-Read)可重复读:MySQL默认隔离级别,事务1未关闭时,事务2修改或插入新数据并提交后,事务1前后查询结果一致,直到关闭事务重新查询才能看到事务2更新后的数据。 RR隔离级别下的unique失效:事务1未关闭时,事务2删除原表中的一条数据,此时是事务1仍能看到已被删除的数据,此时事务1插入一条和原数据主键不冲突,唯一性索引unique冲突的数据时,确可以成功插入。 RR隔离级别下的更新冲突:事务1未关闭时,事务2插入一条数据并提交,此时事务1看不到事务2插入的数据,但此时如果update事务提交的数据,是可以成功update的,且可以查看修改后的新增数据;此时若事务2未关闭,看到的是事务1未update的数据。
5、共享锁、排它锁和表级意向锁
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。
排它锁(X):允许获得排它锁的事务更新数据,但是阻止其他事务获得相同数据集的共享锁和排它锁。
共享锁(S)之间不互斥,读读操作可以并行
排它锁(X)是互斥关系,读写,写写操作不可以并行
事务A和B,事务A锁住了表中的一行,加了行锁S,只能读不能写,之后事务B申请整个表的写锁,理论上能更改任意一行,包括S那一行,但此时和事务A就冲突了。
表级意向锁主要解决这个冲突,事务A必须先申请一个意向共享锁(IS),事务B申请X时,发现表上已经有IS了,则事务B会阻塞。
意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁。
意向排它锁(IX):表示事务准备给数据行加入排他锁,说明事务在一个数据行加排它锁前必须先取得该表的IX锁。
6、行锁
InnoDB行锁是通过给索引项加锁实现的,如果没有索引,会通过隐藏的聚簇索引来对记录加锁,如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。
行锁(Record Lock):对索引项加锁,即锁定一条记录;
间隙锁(Gap Lock):对索引项之间的间隙、对第一条记录前的间隙或最后一条记录后的间隙加锁,即锁定一个范围的记录,不含记录本身;
Nest-key Lock:锁定一个范围的记录并包含记录本身。
7、锁的兼容性
意向锁之间是互相兼容的,S锁之间是互相兼容的,X锁和所有锁冲突 X S IX IS X 冲突 冲突 冲突 冲突 S 冲突 兼容 冲突 兼容 IX 冲突 冲突 兼容 兼容 IS 冲突 兼容 兼容 兼容
8、死锁
如果锁不兼容的情况下,通常会产生阻塞。
9、索引加锁过程的差异
对于唯一性索引和主键,加锁过程的差异 RC隔离级别: 对于非唯一性索引来说,加锁会有2个X锁,一个位于唯一性索引的键值记录,另一个则根据对应的聚簇索引的键值(如主键索引)加X锁; 对于非唯一性索引来说,也会关联锁定的相应的主键聚簇索引项。 RR隔离级别:除了上诉2个X锁,还有额外的意向锁。