黑马程序员技术交流社区
标题:
有始有终--数据库事务与隔离级别
[打印本页]
作者:
学python的排骨
时间:
2019-8-16 09:41
标题:
有始有终--数据库事务与隔离级别
1. 定义
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
事务最重要就是,四大特性(ACID)和隔离级别
2. 四大特性:原子性、隔离性、一致性、持久性
1. 原子性(atomicity)一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。2. 一致性(consistency)数据库总是从一个一致性的状态转换到另一个一致性的状态。例如:银行转账的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)3. 隔离性(isolation) 通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。 例如:在A向B转账的过程中,只要所处事务还没有提交,其他事务查询A或者B账户的时候,两个账户的金额都不会发生变化; 如果在A给B转账的同时,有另外一个事务执行了C给B转账的操作,那么当两个事务都结束的时候,B账户里面的钱应该是A转给B的钱加上C转给B的钱再加上自己原有的钱;4. 持久性(durability)一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)
3.
隔离级别
3-1:不考虑隔离性会出现什么问题?
---
脏读、不可重复读、幻读
1. 脏读
脏读:一个事务读取到另一个事务未提交的数据的情况被称为脏读。举例说明: 转账的例子。A向B转账,A执行了转账语句,但A还没有提交事务(还没committed),B读取数据,发现自己账户钱变多了!B跟A说,我已经收到钱了。 A此时回滚事务【rollback】,那么原来所有的操作全部回退了,等B再查看账户的钱时,发现钱并没有多。分析: 出现脏读的本质就是因为操作(修改)完该数据就立马释放掉锁,导致读的数据就变成了无用的或者是错误的数据。解决(Read committed): 从上面的分析也能看出来,解决的方式就是把锁释放的位置放到事务提交之后 。这样的话,在事务还未提交之前,其他的事务对该数据是无法进行操作的,这也是Read committed避免脏读的做法;
2. 不可重复度
不可重复读:一个事务中,两次读取的数据的内容不一致。;一个事务读取到另外一个事务已经提交的数据,也就是说一个事务可以看到其他事务所做的修改 ;举例说明: 事务A在读取一条数据,得到结果a,事务B把这条数据改成了b并提交了事务,这个时候事务A再次去读取这条数据,得到的结果是b。这样就发生了不可重复读; 即:A、B同时操作一个数据,当A还在操作,第一次读取是a,当B提交了数据,修改成了b,A此时去读又读的是b。正确的是他应该读到原来的a,等操作完了再和B提交的合并分析: Read committed 采用的是语句级别的快照!每次读取的都是当前最新的版本!解决: Repeatable read避免不可重复读是事务级别的快照!每次读取的都是当前事务的版本,即使被修改了,也只会读取当前事务版本的数据。
3. 幻读
幻读/虚读:一个事务中 两次读取的数据的数量不一致 。 是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致 (幻读是事务非独立执行时发生的一种现象);举例说明: 例如事务A对一个表中符合条件的一些数据做了从a修改为b的操作,这时事务B又对这个表中插入了符合A修改条件的一行数据项,而这个数据项的数值还是为a并且提交给数据库。而操作事务A的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务B中添加的,就好像产生幻觉一样,这就是发生了幻读。解决: 但在MySQL实现的Repeatable read配合间隙锁不会出现幻读; 使用间隙锁锁住符合条件的部分,不允许插入符合条件的数据。
间隙锁
间隙锁:当我们用范围条件检索数据而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合范围条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”。InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(间隙锁只会在Repeatable read隔离级别下使用)。
InnoDB使用间隙锁的目的有两个:
为了防止幻读
满足恢复和复制的需要
MySQL的恢复机制要求:在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录,也就是不允许出现幻读 ;
所以要考虑隔离性,隔离又存在存在级别。
1. Read uncommitted:未提交读 (读取尚未提交的数据 :哪个问题都不能解决) 最低级别,会出现脏读、不可重复读、幻读。2. Read committed:已提交读 (读取已经提交的数据 :可以解决脏读 ---- oracle默认的) 避免脏读,会出现不可重复读和幻读。3. Repeatable read:可重复读 (重读读取:可以解决脏读 和 不可重复读 ---mysql默认的) 避免脏读和不可重复读,会出现幻读(在MySQL实现的Repeatable read配合gap锁不会出现幻读!)。4. Serializable :串行化 (相当于锁表) 避免脏读、不可重复读、幻读。
事务的基本操作
1. 开启事务() 开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中 begin; 或者 start transaction;2. 提交事务() 将缓存中的数据变更维护到物理表中 commit 3. 回滚事务() 放弃缓存中变更的数据 rollback
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2