3-Mysql事务与锁详解
Mysql事务与锁详解
数据库事务的定义
事务是数据库管理系统(DBMS) 执行过程中的一个逻辑单位(整体不可分割,原子性),由一个有限的数据库操作序列构成。
事务的四大特性(ACID)
原子性(Atomicity)
最小逻辑单位,不可分割,要么都成功,要么都失败。
依赖事务日志 undo.log实现。
一致性(Consistency)
事务开始之前,事务结束之后,数据都要是合法的;数据库自身的完整性约束;用户自定义的完成性的约束
隔离性(Isolation)
多个事务间互不干扰。
持久性(Durability)
依赖 redo.log +双写缓冲实现。
事务并发的问题
脏读
在一个事务内读取到另一个事务未提交的数据。
不可重复读
在一个事务内读取到另一个事务已提交的数据。
更新update或删除delete导致的数据变化叫做不可重复读。
幻读
在一个事务内读取到另一个事务已提交的插入数据。
只有当插入insert导致行数的增加才叫做幻读。
总结:事务并发的三大问题实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。
事务隔离级别
Read Uncommitted(未提交读)一未解决任何并发问题
事务未提交的数据对其他事务也是可见的,会出现脏读。
Read Committed(已提交读)一解决脏读问题
一个事务开始之后,只能看到已提交的事务所做的修改,会出现不可重复读。
Repeatable Read(可重复读:Mysql5.7默认的事务隔离级别)一解决不可重复读问题
在同一个事务中多次读取同样的数据结果是一样的,这种隔离级别未定义解决幻读的问题。
但是在mysql InnoDB的存储引擎中是已经解决了幻读的问题了(因为使用了间隙锁,能够阻塞插入,防止了幻读问题),所以默认用的就是Repeatable Read(可重复读)。
Serializable(串行化)一解决所有问题
最高的隔离级别,通过强制事务的串行执行。导致并发度的效率大大降低。
Mysql InnoDB 对事务隔离级别的支持程度
快照读: 生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级 或事务级)的一致性读取 (MVCC) Multi Version Concurrency Control。
1 |
|
当前读: 在读取数据前,对其加锁,阻止其他事务对数据进行 修改(LBCC)Lock Based Concurrency Control。基于最新的数据去操作的时候就是当前读
1 |
|
RC和RR的区别
RR的快照建立时问是第一次查询的时候,所以未提交的事务和其后的事务的事务是不能看见的。
RC的快照建立时问是当前select,所以能够看到其他事务已提交的数摆。
具体的机制就是两种隔离级别的ReadView的差异。
Mysql 锁基本类型
行锁与表锁区别
锁定粒度:表锁 > 行锁
加锁效率:表锁 > 行锁
冲突概率:表锁 > 行锁
并发性能:表锁 < 行锁
1、一张表没有索引,为什么会锁表?
一张表里如果有主键索引,会将它作为聚簇索引,其次如果没有主键索引,它会找表里不为空并且是唯一的索引作为聚簇索引,再其次如果既没有主键也没有不为空并且是唯一的索引,它就会用隐藏的字段rowid作为聚簇索引;这时它会进行全表扫描,锁住所有rowid的行,就导致整张表锁住了。
2、同一条数据唯一索引加锁,为什么阻塞主键索引加锁?
二级索引加锁时,因为二级索引是非聚簇索引,加锁时会通过非聚簇索引找到聚簇索引(也就是主键索引),锁住的其实是聚簇索引,所以就导致加锁冲突了。
InnoDB Locking
行锁:共享锁(Shared Locks)
共享锁又称为读锁,简称S锁
共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数 据,但是只能读不能修改。
加锁方式:
1 |
|
释放锁方式:事务结束释放锁
行锁:排他锁(Exclusive Locks)
排他锁又称为写锁,简称X锁。
排他锁不能与其他锁并存,如一个事务获取了一个数据行的排他锁, 其他事务就不能再获取该行的锁(共享锁、排他锁),只有该获取了排他锁的事务是可以对数据行进行读取和修改。
加锁方式:
- 自动:
DELETE/UPDATE/INSERT
DML语句默认动加上排他锁(X锁) - 手动:
FOR UPDATE
语句
释放锁方式:事务结束释放锁
意向共享锁(IS)/意向排他锁(IX)
意向锁是又存储引擎自己维护的,用户无法手动操作意向锁。
作用:为了提升加表锁的效率。
- 意向共享锁(Intention Shared Locks,简称IS锁):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须取的该表(表级别)的意向共享锁(IS锁);类似JAVA中的偏向锁。
- 意向排他锁(Intention Exclusive Locks,简称IX锁):表示事务准备给数据行加入排他锁,也就是说一个数据行加排他锁前必须取的该表(表级别)的意向排他锁(IX锁);类似JAVA中的偏向锁。
锁的算法(在什么样的情况下锁的范围)
记录锁(Record Locks):锁定记录
当你使用
FOR UPDATE
语句进行加锁时,精准命中一条记录,就会锁住该条记录;
间隙锁(Gap locks):锁定范围
当你使用
FOR UPDATE
语句进行范围查询或者等值查询时,如果没有命中任何数据记录的时候,就会锁住这个范围的区间;注意:相同的间隙锁不排斥,排斥的是插入
比如我使用
1
SELECT * FROM t WHERE id = 6 FOR UPDATE;
这时锁住的是4-7之间的范围,这时我再使用该条语句,是不会排斥的,但是,当我进行插入时就会排斥
1
2
INSERT INTO `t`(`id`,`name`) VALUES (5,"张三");
INSERT INTO `t`(`id`,`name`) VALUES (6,"张三");
临键锁(Nest-key Locks):锁定范围加记录
InnoDB存储引擎行锁的默认算法;临键锁包含了间隙锁;它能够阻塞插入所以防止了幻读的问题;
条件是必须是范围查询,同时命中数据的记录(包含记录和区间);如果用等值查询是不满足条件的即包含记录和区间的;
会锁住最后一个记录(Record)的下一个key的左开右闭的区间。