事务是什么
标准解释:事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列组成。
通俗来说是:事务就是由dml语句构成的一个不可分割的执行模块,要么所有语句执行都成功,要么都失败,没有其它的情况。
在了解了事务的基本概念之后,我们就要想了,既然说事务只是数据库管理系统一个逻辑单位,那么在同一时刻肯定会有很多个事务在同时执行,那这就迁出来一个问题了:数据库系统如何保证事务数据读取时的准确性呢?
这就需要牵出事务的ACID特性了,在这需要特别指出的是对于Mysql来说,我们常用的InnoDB和MyISAM引擎中,只有InnoDB支持事务的操作。
事务的ACID
ACID,即
- A ,Atomicity,原子性。
- C,Consistency,一致性
- I,Isolation,隔离性
- D,durability,持久性
原子性,就是操作要么都成功,要么都失败;一致性,就是事务前后数据库的完整性约束没有被破坏;隔离性,就是每个事务是完全透明的,不应该相互影响;持久性,就是事务提交之后,数据要能被永久在硬盘中能够保存。
原子性、持久性这三两个事务特性可以不用太深究,在实际的业务中也很少为这两个特性而花时间,一致性是其它三个特性共同作用的结果,也不用太深究,咱重点来说说这个隔离性。
事务的隔离性
当数据库系统中有个事务并发执行时,不可避免的会有操作同一张表数据的情况,在sql92标准中针对多事务并发执行给出了以下三种结果
- 脏读,事务A读取到了事务B中未commit的数据
- 不可重复读,事务B进行了删除/更新操作导致A事务前后读取到的数据不同
- 幻读,事务B插入了数据导致A事务前后读取到的数据不同
针对以上三种结果,sql92标准定义了一下四种事务隔离级别:
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(Read Uncommited) | 可能 | 可能 | 可能 |
已提交读(Read Commited) | 不可能 | 可能 | 可能 |
可重复读(Repeatable Read ) | 不可能 | 不可能 | Innodb不可能 |
串行化(Serializable) | 不可能 | 不可能 | 不可能 |
这四种隔离级别的并发读是由上至下降低的
有了上面的知识之后,咱们来探讨一个更深入的问题:如果要解决读一致性的问题,保证事务中前后两次读取的数据保持一致,要怎么做呢?
其实解决的方法有两种:
- 在读数据之前,对其加锁,阻止其它的事务对数据进行修改,即Lock Based Concurrency Control,LBCC
- 生成一个数据请求时间点的一份一致性数据快照,并用这个快照来提供一定级别的一致性读取(MVCC)Multi Version Concurrency Controll
锁
锁,是锁住了什么呢?其实就是锁住了这条数据的主键索引。
锁有什么类型呢?行锁和表锁
类型 | 解释 |
---|---|
共享锁(行锁) | A事务和B事务可以同时对一行数据 进行锁定,但是被锁定的数据行只能读不能写 |
排他锁(行锁) | A事务对数据行进行加锁后,不允许其它事务再获取共享锁和排他锁,只有A事务能对其进行读取和修改 |
意向共享锁 IS(表锁) | 事务准备给数据行加入共享锁必须要先取得IS锁,这样其他事务对数据加共享锁的时候就只要先判断有没有这个锁存在,如果有了就不许再加排他锁了 |
意向排他锁 IX(表锁) | 事务准备给数据行加入排他锁必须要先取得IX锁,这样其他事务对数据行加共享排他锁的时候就只要先判断有没有这个锁存在,如果有了就不许其他事务再加排他锁了 |
排他锁又有下面三种锁的类型:
类型 | 解释 |
---|---|
记录锁(Record Lock) | 唯一性索引(唯一、主键)等值查询,精准匹配 |
临键锁(Next-Key Lock) | 范围查询,包含记录和区间 |
间隙锁(Gap lock) | 封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围 |
MVCC
事务A在进行读取时是读取了一个当前时刻的快照版本,该快照版本包括了当前时刻所有其它事务已提交的数据,其它事务未提交的数据对事务a的数据不会有任何的影响,高效地解决了读-写问题。
隔离性实现总结
事务的隔离性通过了mvcc+锁的机制来保证,我们在使用mysql innodb引擎的时候放心用就行了。