事务基本概念
什么是事务
事务:指一组操作,可以是一个SQL语句也可以是多个SQL语句;
事务的特性
一般来说,事务要满足四大特性(ACID)
- 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中的操作要么都成功要么都失败;
- 一致性(consistency):事务必须是使数据库从一个一致性状态变成另外一个一致性状态;
- 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及其数据并发的其他事务是隔离的,互不干扰;
- 持久性(durability):若一个事务已经提交,那么对数据库中的数据变化是永久的,不会再有任何影响;
如何理解原子性
原子性其实很简单,举个转账的例子:
A转账100元给B,其实该转账操作由两步组成,一步是A扣除100元,另外一步是B增加100元;
但是这两个操作是不可以分割的,也就是说这两步共同组成一个事务,不可以再分;
如果A扣除100元之后,在B增加100元之前机器出现了故障,那么该事务便应该直接失败;
原子性的核心是关注状态,要么全部成功要么全部失败;这也是原子性与一致性的核心区别;
如何理解一致性
一致性我们还是列举转账的例子:
A转账100元给B,假设其他用户可以观测到每个用户的余额,那么其他用户要么只能观测到A未转账给B,要么只能观察到A已经转账给B;而对于中间过程A减少了100元、B增加了100元这个操作是不可见的;
一致性关注数据的可见性,中间状态的数据对于外部不可见,只有最初状态与最终状态可见;
如何理解隔离性
隔离性的话,理解起来比较复杂,我们慢慢来讲;
首先我们要明确,数据库是允许多个并发执行同时进行的,什么叫同时并发执行,举个简单例子
并发执行的例子:
还是以转账为例子,A转账给B的同时,C转账给D是可以互不影响同时进行的;
但是大家都知道,一旦涉及到并发的内容,那么就很有可能出现并发安全问题;
以下几个概念是隔离性需要解决的问题
脏读
指一个事务正在访问数据,且对于数据进行了修改,但是还没有提交到数据库中;而另外一个事务也访问这个数据,然后使用了这个数据;
假设A的余额有100元,然后他进行了充值等操作,变成了200元,这个时候B去访问他的余额,但是这个时候因为断网等原因,A的余额进行了回滚,此时A余额为100元,但是B却查到余额为200元;
或者当B查询余额的时候,A的事务还未提交,B获取的A的余额为100元,但是实际上A的余额为200元;这种也是脏读;
时间 | 事务A | 事务B |
---|---|---|
t1 | 查询余额,得到余额为100元 | |
t2 | 充值余额为200元 | |
t3 | 查询余额,得到余额为200元 | |
t4 | 事务回滚 | |
t5 | 事务提交,得到余额为200元 |
简单概括便是,我得到的数据跟实际的数据不一致的问题;
不可重复读
指一个事务中查询同一条记录两次,却得到了两个不同的结果;
时间 | 事务A | 事务B |
---|---|---|
t1 | 查询余额,为100元 | |
t2 | 更新余额为200元 | |
t3 | 查询余额,为200元 | |
t4 | 事务提交,最后查询结果为200元 |
幻读
指一个事务读取了两次数据,这两次的读取过程中另外一个事务添加了数据,使得第二次读取数据的集合不一样;
时间 | 事务A | 事务B |
---|---|---|
t1 | 查询数据库中用户数目,为10条 | |
t2 | 插入一条新的用户数据 | |
t3 | 查询数据库中用户数目,为11条 |
其他的问题
以上三个属于非常重要的知识点,而下面的问到的情况较少;
第一类丢失更新
指一个事务撤销的时候,把其他事务的更新数据覆盖了。这是种很严重的问题;
比如A余额为100元,然后取出10元,此时B转入10元,A事务因为某些原因产生了回滚,按道理余额应该是110元,但是却因为回滚而使得A余额为100元的现象;
可以看到这种主要是影响到了用户
第二类丢失更新
指A事务执行覆盖B事务所做的更新,使得B事务操作丢失;
A事务使得某个账号增加10元,未提交事务的时候,另外一个事务使得该账号减少10元,然后A事务提交,结果账号余额为110元,丢失了B事务的修改,这便是第二类丢失更新;
实际上第二类更新与不可重复读是同一种问题;
小总结
本来我有点不理解,不可重复读与幻读,因为我觉得修改之后读出不同的数据很正常啊;
我后面反应过来,主要是因为一个事务不能被其他事务干扰,而这两种情况属于已经被干扰了的情况;所以我们要用事务隔离级别来解决这些出现的问题;
事务隔离级别
SQL标准定义了四种隔离级别,MySQL都支持,下面是隔离级别从低到高
- 读未提交
- 读提交
- 可重复读
- 串行化
从低到高越能保证数据的完整性与一致性,但是随之性能损耗也越大;
InnoDB默认的隔离级别是可重复读级别;
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
√代表可能出现,×代表不会出现;
读未提交、读提交比较少用,基本上还是以可重复读为主;
总结
本篇博客主要是介绍了基本的事务相关概念,而之后会推出博文来整理四种隔离级别分别是如何实现的,点个关注吧