写在前面
这是一篇读(重)书(点)笔(摘)记(要)~内容为《高性能 MySQL》第一章~sql
and 七夕快乐,因此今天的配图是粉红色的(๑•̀ㅂ•́)و✧数据库
事务
简单的说,事务就是一组原子性的 SQL 查询,这一组 SQL 要么所有执行成功,要么所有执行失败。这里简单介绍一下事务的 ACID,ACID 表示原子性、一致性、隔离性和持久性。markdown
- 原子性:一个事务是不可分割的最小工做单元,整个事务要么所有成功,要么所有失败,不可能只执行中间的一部分操做。
- 一致性:执行事务是使得数据库从一个一致性状态到另外一个一致性状态,若是事务最终没有被提交,那么事务所作的修改也不会保存到数据库中。
- 隔离性:一般来讲,一个事务提交以前对其余事务是不可见的,可是这里所说的不可见须要考虑隔离级别,好比未提交读在提交前对于其余事务来讲也是可见的,隔离级别,在下面会详细讲。
- 持久性:事务一旦被提交,那么对数据库的修改会被永久的保存,即便数据库崩溃修改后的数据也不会丢失。
隔离级别
SQL 标准中定义了四种隔离级别,这里简单介绍一下这四种隔离级别。性能
- 未提交读:未提交读的意思是,事务中的修改,即便没有提交,对其余事务也都是可见的,可是这样会出现脏读,通常状况下,一般都不会使用未提交读。
- 提交读:提交读的意思是,一个事务所作的修改在提交以前对其余事务都是不可见的,这个级别也叫作“不可重复读”,由于执行两次相同的操做,可能会获得不一样的结果。
- 可重复读:可重复读解决了脏读的问题,这个级别保证了同一个事务屡次读取一样记录的结果是一致的,可是这个隔离级别没法解决幻读的问题,所谓幻读就是说,当某个事务读取范围数据时,另外一个事务又在该范围内插入了新的记录,当以前的事务再次读取该范围数据时,会产生幻行。InnoDB 存储引擎经过 MVCC 解决了幻读的问题,可重复读是 MySQL 默认的事务隔离级别。
- 可串行化:是最高的隔离级别,避免了前面说到的幻读问题。可串行化会给读取的每一行都加锁,因此可能致使大量超时和锁争用的问题,实际中不多使用这个隔离级别。
死锁
死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源。解决死锁的方法就是回滚一个或者多个事务。spa
MVCC
MVCC 能够看作是行锁的一个变种,在不少状况下 MVCC 能够避免加锁,所以开销更小,不一样事务型存储引擎对于 MVCC 的实现各有不一样。 MVCC 的实现是经过保存数据在某个时间点的快照来实现的。也就是说,无论执行多长时间,每一个事务看到的数据都是一致的。根据事务的开始时间不一样,每一个事务对同一张表,同一时刻看到的数据多是不同的。这里简单介绍一下 InnoDB 的 MVCC。 InnoDB 的 MVCC 经过在每行记录后面保存两个隐藏的列来实现。这两个列,一个保存了行的建立时间,一个保存了行的过时时间,存储的不是实际的时间,而是版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会做为事务的版本号,用来和查询到的每行记录的版本号做对比。下面详细介绍一下在可重复读隔离级别下,MVCC 的具体操做。code
- SELECT
- InnoDB 会根据如下两个条件检查每条记录:
- 只查找版本小于等于事务版本号的行
- 只查找未定义删除时间或者删除时间大于事务版本号的行
- INSERT
- InnoDB 为新插入的每一行保存当前的系统版本号做为行版本号
- DELETE
- InnoDB 为删除的每一行保存当前的系统版本号做为行的删除版本号
- UPDATE
- InnoDB 新增一条记录,保存当前系统版本号做为新增行的版本号
- 在被删除记录的原始行,保存当前系统版本号做为被删除记录行的删除版本号
优势:orm
- 由于有了两个隐藏列来记录数据的状态,因此大多数读操做均可以不加锁
- 性能好,同时能够保证读取的数据是正确的
缺点:索引
- 须要额外的空间记录每行的状态
- 须要行状态的维护和检查
如何解决幻读
MVCC 解决幻读的时候使用了间隙锁,也就是 next-key lock,这部分就要先从 InnoDB 的三种行锁提及:事务
- Record Lock:单个行记录上的锁,锁住的是索引
- Gap Lock:区间锁,锁定一个区间范围,但不包括记录自己,开区间
- Next-Key Lock:间隙锁,Record Lock + Gap Lock
举个简单的例子,资源
select id from user where id > 15 and id < 30
复制代码
图示清楚的表示了间隙锁~
总结
这一章发的貌似有点晚了,应该在索引以前发的。But,依然感谢观看~ 最后表白我潘,mua! (*╯3╰),七夕快乐~
Reference
《高性能 MySQL》