本文是看完b站视频 https://www.bilibili.com/video/BV1x54y1979n?from=search&seid=1274784708496063961 所做的笔记
看懂篇文章需要有Mysql索引的相关知识
1.什么是事务
事务是由DBMS执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
2.支持事务的存储引擎
InnoDB、NDB
3.事务四大特性
- 原子性(Atomicity) 原子性是指事务中不可分割的工作单位。
- 一致性(Consistency ) 事务必须使数据库从一个一致性状态切换到另外一个一致性状态
- 隔离性(Isolation) 隔离性是指一个事务的执行不能被其他事务干扰,并发执行的各个事务之间不能互相干扰。
- 持久性(Durability) 持久性是指一个事务一旦被提交,那么这些数据就会永久存在磁盘中
总结:ACD特性都是为了解决I的
4.事务并发带来的问题
4.1 脏读(Dirty read)
事务A读取到了事务B 未提交 的数据(该数据只存在内存中的,未持久化到磁盘)
4.2 不可重复读(Non-repeatable read)
事务A读取到了事务B 已提交 的数据而造成的。这种操作仅限于 update 与 delete 。
4.3幻读(Phantom)
事务A用 范围查询 读取到了事务B 已提交 的数据而造成的。这种操作仅限于 insert 。
总结:事务并发的三大问题其实都是数据库的读一致性问题,必须由数据库提供一定的事务隔离机制来解决。
5. 事务隔离级别
- Read Uncommitted (读未提交)
- Read Committed (读已提交):解决脏读。
- Repeatable Read (可重复读):解决脏读、不可重复读。 Mysql默认
- Serializable(串行化):解决脏读、不可重读读、幻读。
事务隔离级别 脏读 不可重复读 幻读 Read Uncommitted (读未提交) 可能 可能 可能 Read Committed (读已提交) 不可能 可能 可能 Repeatable Read (可重复读) 不可能 不可能 对InnoDB不可能 Serializable(串行化) 不可能 不可能 不可能
6. 事务隔离级别解决方案
第一种:
在读取数据前,对其加锁,阻止其他事务对数据进行修改——Lock Based Concurrency Control(LBCC)。
第二种:
生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取——Multi Version Concurrent Control(MVCC)。
7. InnoDB的锁
说明:锁的类型有 共享/排它锁、意向锁、自增锁 , 而 间隙锁、记录锁、临键锁、插入意向锁 可以理解为是锁的算法
7.1 共享/排它锁(Shared and Exclusive Locks)
简介:共享锁和排它锁都是 行锁。
共享锁(S锁):又称读锁。允许多个事务对于同一数据可以共享一把锁,即都能访问到数据,但是只能读不能修改。
加锁方式:select * form student where id = 1 lock in share mode
释放锁:commit/rollback
排他锁(X锁):又称写锁。排他锁不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务不能再获取该行的锁(S锁、X锁),只有该行获取了排他锁的事务是可以对数据行进行读取和修改。
加锁方式:
自动:update/delete/insert 默认上X锁
手动:select * form student where id = 1 for update
释放锁:commit/rollback
7.2 意向锁(Intention Locks)
简介:意向锁是由数据引擎自己维护的,用户无法手动操作意向锁。意向锁是表锁。
上表锁成功的前提:该表中已经没有其他 事务的行锁。
意向共享锁(IS锁):事务给数据加上S锁之前,必然要先给该数据所在的表加上IS锁。
意向排他锁(IX锁):事务给数据加上X锁之前,必然要先给该数据所在的表加上IX锁。
用处:提高加表锁的效率。当需要对该表上表锁时,直接查看该表有没有意向锁即可。
7.3 记录锁(Record Locks)
简介:记录锁就是为某行记录加锁,它封锁该行的索引记录。
用处:数据的等值查询
7.4 间隙锁(Gap Locks)
简介:对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”
举例:举例来说,假如lock_example表中只有11条记录,其id的值分别是1,2,…,10,11,下面的SQL:
Select * from lock_example where id > 10 for update;
InnoDB 不仅会对符合条件的 id值为 11 的记录加锁;也会对 id大于11(这些记录并不存在)的“间隙”加锁。作用:阻塞插入,防止幻读,这就是为什么InnoDB可以解决幻读的原因
7.5 临键锁(Next-key Locks)
简介:可以理解为记录锁+间隙锁。这个临键锁,锁住的是最后一个索引记录的下一个左开右闭
作用:阻塞插入,防止幻读
更多锁的概念,请查看这篇博客:https://zhuanlan.zhihu.com/p/127919778
8. 锁的原理
InnoDB行锁是通过给表上的索引项加锁来实现的。
聚集索引的情况:
1)显式定义primary key
2)表中的字段若有unique key + not null 的约束,则该字段会升级为索引
3)表中的隐藏字段: _rowid 会升级为索引8.1 表中没有索引
当表中没有索引时,_rowid会作为表的聚集索引,通过查找数据时,只能通过全表扫描,然后又会把每一行的_rowid锁定起来,从而造成锁表的情况。
8.2 表中有主键索引和唯一索引
InnoDB有聚集索引(主键)和 二级索引(非主键索引)
当使用有唯一索引的字段的字段去锁定数据(select * from student where name = “Xavier” for update; 这里name是唯一索引,上了X锁)时,其他事务不能用主键索引和唯一索引 去读取该行的数据。因为唯一索引是二级索引,然后他会找到本行的主键,然后回表主键索引,从而导致主键也被锁了。
想了解更多的Mysql索引,看这篇文章:http://www.liuzk.com/410.html