关于数据库的事务
对于数据库的学习,除了会编写SQL语句,会用程序连接数据库进行增删查改操作,还必须对数据库的事务的概念和是数据库索引有一定的理解(这是一篇全是字的文章,没有图)
本文内容
- 什么是事务
- 事务的ACID
- 事务的隔离级别
什么是事务
事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元,是并发控制的基本单位,简单通俗的说,它就是一个操作序列,这些操作要么全部成功,要么全部失败,举个例子:A去银行给B转账,需要进行两个操作,A的账户的金额减少,B的账户金额增加,这两个操作如果有一个失败,那么A和B的账户余额都不能变化,这个转账过程就是一个事务
事务的ACID
事务的ACID就是事务的四大特性:
- 原子性(Atomicity):事务是一个完整的操作,而且每步操作都是不可再分的,要么全部执行,要么全部不执行
意思就是,A给B转账,A账户金额减少,B账户金额增加,这两个操作一起才是完整的操作,而且这两个操作都不能再细分,所以这两个操作要么全部执行,要么全部不执行,不能只执行一个
- 一致性(Consistency):当事务完成时,数据必须保存在一致状态
意思就是,A给B转账后,A金额减少,B金额增加,这叫做数据一致,如果出现A金额减少,B金额不变,这就是数据不一致
- 隔离性(Isolation):并发事务之间互不影响,相互独立
意思就是,假如A和C同时给B转账,那么这是两个事务,并且不能互相影响,B的最后一定是收到两个人的转账,隔离性有四个级别,也就是事务的隔离级别,下面再介绍
- 持久性(Duration):事务完成后,数据应在数据库持久保存
意思就是说,A给B的转账结果,在没有别的事务操作之前,都会一直在数据库里保存,不会自动恢复
事务的隔离级别
在了解事务的隔离级别之前,需要了解几个现象
- 脏读
脏读就是一个事务读取了另一个事务还没有提交的数据,而这个数据是可能回滚的
举个例子,假设A有100块钱,A对自己的账户余额进行查询,当还没有查询到结果的时候,B从A的账户取了100块钱,刚好这个时候A查询到了自己的余额为0,于是准备存100块钱进去,但是这时候B出现问题,并没有将100块钱取出来,回滚了事务,而这个时候A存了100块钱,然后提交,这个时候,A的余额还是100块钱
在这个例子中,A读到的余额是0元就是个脏数据,而这个数据是由于B的事务没有进行隔离造成的
- 不可重复读
不可重复读就是,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。
举个例子,A还是100块钱,A首先查看自己的余额,显示了100,这个时候B又上线了,他又取走了100块钱,然后提交了事务,在这个过程中,A还没有提交事务,然后A又查看一次自己的余额,发现余额变成了0
在A的事务里面,A只进行了两次查询操作,但是两次的结果都不一样,所以这就是由于B的事务对A的事务的影响
不可重复读和脏读的区别是,脏读是一个事务读取了另一个事务还没提交的脏数据,而不可重复读则是读取了另一个事务已经提交的数据。
- 幻读
幻读,是指当事务不是独立执行时发生的一种现象 。
举个例子,A还有100块钱,A要统计自己的全部余额,第一次统计,100元,这个时候B刚好往A的账户存了100元,然后提交了事务,这个时候A刚好打算提交统计结果,然后发现自己的账户变成了200元
在这个例子中,A两次统计的结果不一样,就像出现了幻觉一样,这就是幻读
这个例子看起来和不可重复读很相似,但是注意我的用词,不是查看余额,而是统计余额,这里面有个什么区别,查看是对一个数据查看,统计是对一堆数据进行统计,所以这也是不可重复读和幻读的区别,不可重复读是对数据表里面的一个数据项的两次操作出现不一样的结果,幻读是对一堆数据统计出现不一样的结果
在了解了这几个现象之后,就很容易解释事务的隔离级别了,上面的三种情况都是由于事务之间没有隔离,从而产生的问题,所以不同的业务需要对不同的情况进行隔离
- 读未提及(read_uncommitted): 幻读,不可重复读和脏读均允许,效率高,隔离级别最低
- 读已提交(read_committed):允许幻读和不可重复读,但不允许脏读
- 可重复读(repeatable_read):允许幻读,但不允许不可重复读和脏读
- 顺序读(serializable):幻读,不可重复读和脏读都不允许,隔离级别最高,但效率低
这四个级别从上往下,效率逐级降低,隔离级别逐级增高,安全性也逐级增高
在Oracle和MySQL里面都有默认的事务隔离级别,Oracle默认read_committed,MySQL默认repeatable_read
下一篇,数据库索引:https://blog.youkuaiyun.com/Dongroot/article/details/88765167