1、什么是数据库事务?
-
数据库事务的典型场景?
简单来说就是在一个业务操作中需要对多表执行写操作。
-
什么是事务?
事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
-
哪些存储引擎(Storage Engine)支持事务?
InnoDB、NDB(集群存储引擎)
-
事务的四大特性?(ACID)
原子性(Atomicity)、一致性(Consistent)、隔离性(Isolation)、持久性(Durable)
-
事务并发会带来什么问题?
读一致性问题:事务并发引起的的数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决
- 脏读(读取到其他未提交事务的数据)
- 不可重复度(读取到其他事务提交的数据【update、delete】)
- 幻读(读取到其他事务提交的数据【insert】)
用来实现事务隔离级别的标准
-
Read Uncommitted(未提交读)
-
Read Committed(已提交读):解决脏读
-
Repeatable Read(可重复读):解决脏读、不可重复读
-
Serializable(串行化):解决事务并发的所有问题
InnoDB对事物隔离级别的支持程度
2、事务并发会带来的问题及如何解决?
如果要解决读一致性的问题,保证一个事务中前后两次读取数据一致,实现事务隔离,应该怎么做?
- 在读取数据前,对其加锁,阻止其他事务对数据进行修改--Lock Based Concurrency Control(LBCC)
- 生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取--Multi Version Concurrency Control(MVCC)【问题:MVCC是怎么实现的?】
1、锁的粒度(表锁与行锁)
表锁与行锁的区别:
内容 | 对比 | ||
---|---|---|---|
锁定粒度 | 表锁 | > | 行锁 |
加锁效率 | 表锁 | > | 行锁 |
冲突概率 | 表锁 | > | 行锁 |
并发性能 | 表锁 | < | 行锁 |
问题:MyISAM和InnoDB分别支持什么粒度的锁?
MyISAM | InnoDB |
---|---|
表锁 | 行锁 |
2、锁的模式(Lock Mode)
-
共享锁(S锁、行锁):Shared Locks
又称为读锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
加锁方式:
SELECT * FROM TABLE WHERE ID = #{id} LOCK IN SHARED MODE;
-
排它锁(X锁、行锁):Exclusive Locks
又称为写锁,排它锁不能与其他锁并存,如一个事务获取了一个数据行的排它锁,其他事务就不能再获取该行的锁(共享锁、排它锁),只有该获取了排它锁的事务可以对数据行进行读取和修改。
加锁方式:
自动:DELETE/UPDATE/INSERT(默认加上X锁) 手动:SELECT * FROM TABLE WHERE ID = #{id} FOR UPDATE;
-
意向共享锁(表锁):Intention Shared Locks
意向锁是由数据引擎自己维护的,用户无法手动操作意向锁。意向共享锁简称IS锁,表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁之前必须先取得该表的IS锁。
-
意向排它锁(表锁):Intention Exclusive Locks
意向排它锁简称IX锁,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁之前必须先取得该表的IX锁。
一个事务要成功的锁住一张表,前提是没有其他任务事务已经锁定了该表中的其中一行数据。当一个事务需要锁定某一行数据时(共享锁或排它锁),不需要去扫描全表数据,只需判断该表现存不存在意向锁即可(意向共享锁、意向排它锁)。
3、行锁算法
- 记录所(Record Locks)
- 间隙锁(Gap Locks)
- 临建锁(Next-key Locks)
3、行锁的原理:到底锁住了什么?
1、锁的作用
解决资源竞争问题
2、锁到底锁住了什么?
是一行数据吗(Row、Record)?
是一个字段吗(Column)?
问题:表为什么一定要有主键?
现象:
-
【不使用索引】当一个表没有主键(没有索引)时,对ID为1的数据进行更新(加排它锁),此时再对ID为2的数据进行更新(加排它锁),结果为失败,无法获取到ID的2的数据的行锁。
-
【主键索引】当一个表有主键(没有索引)时,对ID为1的数据进行更新(加排它锁),此时再对ID为2的数据进行更新(加排它锁),结果为成功,可以获取该行数据数据的行锁。
-
【唯一索引】当一个表有两个字段、其中ID为主键、NAME为唯一索引。假设此时存在一条数据,其ID为1,NAME也为1。这个时候,给ID加上排他锁,再给该行数据的NAME字段加上排他锁,结果为失败。
从以上现在分析,可以得出答案。锁锁住的既不是一行数据、也不是一个字段。从而可以提出猜想,其锁住的应该为索引。
索引组织表(题外话)
-
当一个表指定了primary key时,我们称之为聚集索引
-
当一个表没有primary key,但存在unique key并且不能为空时,表将使用该字段作为聚集索引
-
当一个表既没有primary key,又没有unique key时,InnoDB会创建一个隐藏的列(rowid),将其作为聚集索引(可以用来解释第一个现象)
-
除了聚集索引外,其他索引称为辅助索引(均为B+树)。在InnoDB中,聚集索引和辅助索引的区别。
聚集索引 辅助索引 存储索引和数据 存储二级索引和主键ID
-
4、行锁的算法:什么时候锁住什么范围?
-
记录所(Record Locks)
唯一性索引(唯一、主键)等值查询、精准匹配
-
间隙锁(Gap Locks)
锁住记录不存在的范围,其最主要的作用为阻塞插入
-
临建锁(Next-key Locks)【其算法包含了间隙锁,也解决了幻读问题】
范围查询,包含记录和区间,是InnoDB默认的行锁算法
锁的区间定义: