SQL中事务隔离

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 系列文章目录
  • 前言
  • 一、事务四大特性介绍
  • 二、事务四大特性分析
    • 1.原子性
    • 2.隔离性
    • 持久性
    • 数据库的常见错误
      • 脏读
      • 不可重复读
      • 幻读


前言

作者:渔人
链接:https://zhuanlan.zhihu.com/p/43493165
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

什么是事务数据库几乎是所有系统的核心模块,它将数据有条理地保存在储存介质(磁盘)中,并在逻辑上,将数据以结构化的形态呈现给用户。支持数据的增、删、改、查,并在过程中保障数据的正确且可靠。要做到这点并非易事,常见的例子就是银行转账,A账户给B账户转账一个亿(T1),买一块地盖房子。在这种交易的过程中,有几个问题值得思考:如何同时保证上述交易中,A账户总金额减少一个亿,B账户总金额增加一个亿?
AA账户如果同时在和C账户交易(T2),如何让这两笔交易互不影响?
I如果交易完成时数据库突然崩溃,如何保证交易数据成功保存在数据库中?
D如何在支持大量交易的同时,保证数据的合法性(没有钱凭空产生或消失) ?
C要保证交易正常可靠地进行,数据库就得解决上面的四个问题,这也就是事务诞生的背景,它能解决上面的四个问题,对应地,它拥有四大特性:
原子性(Atomicity): 事务要么全部完成,要么全部取消。 如果事务崩溃,状态回到事务之前(事务回滚)。
隔离性(Isolation): 如果2个事务 T1 和 T2 同时运行,事务 T1 和 T2 最终的结果是相同的,不管 T1和T2谁先结束。
持久性(Durability): 一旦事务提交,不管发生什么(崩溃或者出错),数据要保存在数据库中。
一致性(Consistency): 只有合法的数据(依照关系约束和函数约束)才能写入数据库。


提示:以下是本篇文章正文内容,下面案例可供参考

一、事务四大特性介绍

作者:渔人
链接:https://zhuanlan.zhihu.com/p/43493165
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ACID接下来详细地了解这四大特性:原子性,确保不管交易过程中发生了什么意外状况(服务器崩溃、网络中断等),不能出现A账户少了一个亿,但B账户没到帐,或者A账户没变,但B账户却凭空收到一个亿(数据不一致)。A和B账户的金额变动要么同时成功,要么同时失败(保持原状)。隔离性,如果A在转账1亿给B(T1),同时C又在转账3亿给A(T2),不管T1和T2谁先执行完毕,最终结果必须是A账户增加2亿,而不是3亿,B增加1亿,C减少3亿。持久性,确保如果 T1 刚刚提交,数据库就发生崩溃,T1执行的结果依然会保持在数据库中。一致性,确保钱不会在系统内凭空产生或消失, 依赖原子性和隔离性。可以看出,原子性、隔离性、一致性的根本问题,是不同的事务同时对同一份数据(A账户)进行写操作(修改、删除、新增),如果事务中都只是读数据的话,那么它们可以随意地同时进行,反正读到的数据都是一样的。如果,几个互不知晓的事务在同时修改同一份数据,那么很容易出现后完成的事务覆盖了前面的事务的结果,导致不一致。 事务在最终提交之前都有可能会回滚,撤销所有修改:如果T1事务修改了A账户的数据,这时T2事务读到了更新后的A账户数据,并进行下一步操作,但此时T1事务却回滚了,撤销了对A账户的修改,那么T2读取到的A账户数据就是非法的,这会导致数据不一致。这些问题都是事务需要避免的。

二、事务四大特性分析

1.原子性

begin; -- 开始一个事务
update table set A = A - 1亿; -- 伪sql,仅作示意
update table set B = B + 1亿;
-- 其他读写操作
commit; -- 提交事务

要保证上面操作的原子性, 就得等begin和commit之间的操作全部成功完成后,才将结果统一提交给数据库保存,如果途中任意一个操作失败,就撤销前面的操作,且操作不会提交数据库保存,这样就保证了同生共死。

2.隔离性

作者:渔人
链接:https://zhuanlan.zhihu.com/p/43493165
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

如何保证隔离性原子性的问题解决了,但是如果有另外的事务在同时修改数据A怎么办呢? 虽然可以保证事务的同生共死,但是数据一致性会被破坏。 此时需要引入数据的隔离机制,确保同时只能有一个事务在修改A,一个修改完了,另一个才来修改。 这需要对数据A加上互斥锁:先获得了锁,然后才能修改对应的数据A事务完成后释放锁,给下一个要修改数据A的事务同一时间,只能有一个事务持有数据A的互斥锁没有获取到锁的事务,需要等待锁释放以上面的事务为例,称作T1,T1在更新A的时候,会给A加上互斥锁,保证同时只能有一个事务在修改A。 那么这个锁什么时候释放呢? 当A更新完毕后,正在更新B时(T1还没有提交),有另外一个事务T2想要更新A,它能获取到A的互斥锁吗?答案是不能, 如果T1在更新完A后,就释放了互斥锁,此时T2获取到T1的最新值,并做修改, 如果一且正常,则万事大吉。 但是如果在T2更新A时,T1因为后面的语句执行失败而回滚了呢?此时T1会撤销对A的修改,T2得到的A数据就是脏数据,更新脏数据就会导致数据不一致。所以,在事务中更新某条数据获得的互斥锁,只有在事务提交或失败之后才会释放,在此之前,其他事务是只能读,不能写这条数据的。这就是隔离性的关键,针对隔离性的强度,有以下四的级别(引用自这篇文章):串行化(Serializable,SQLite默认模式):最高级别的隔离。两个同时发生的事务100%隔离,每个事务有自己的"世界", 串行执行。可重复读(Repeatable read,MySQL默认模式):如果一个事务成功执行并且添加了新数据(事务提交),这些数据对其他正在执行的事务是可见的。但是如果事务成功修改了一条数据,修改结果对正在运行的事务不可见。所以,事务之间只是在新数据方面突破了隔离,对已存在的数据仍旧隔离。读取已提交(Read committed,Oracle、PostgreSQL、SQL Server默认模式):可重复读+新的隔离突破。如果事务A读取了数据D,然后数据D被事务B修改(或删除)并提交,事务A再次读取数据D时数据的变化(或删除)是可见的。这叫不可重复读(non-repeatable read)。读取未提交(Read uncommitted):最低级别的隔离,是读取已提交+新的隔离突破。如果事务A读取了数据D,然后数据D被事务B修改(但并未提交,事务B仍在运行中),事务A再次读取数据D时,数据修改是可见的。如果事务B回滚,那么事务A第二次读取的数据D是无意义的,因为那是事务B所做的从未发生的修改(已经回滚了嘛)。这叫脏读(dirty read)。

持久性

如何保证持久性隔离性的问题解决了,但是如果在事务提交后,事务的数据还没有真正落到磁盘上,此时数据库奔溃了,事务对应的数据会不会丢?事务会保证数据不会丢,当数据库因不可抗拒的原因奔溃后重启,它会保证:成功提交的事务,数据会保存到磁盘未提交的事务,相应的数据会回滚

作者:渔人
链接:https://zhuanlan.zhihu.com/p/43493165
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

数据库的常见错误

https://blog.csdn.net/qq_29501587/article/details/52135164

脏读

1、脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
例如:
张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
与此同时,
事务B正在读取张三的工资,读取到张三的工资为8000。
随后,
事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
最后,
事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读

读到了没有用的数据,别人还没提交的垃圾

不可重复读

2、不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
例如:
在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
与此同时,
事务B把张三的工资改为8000,并提交了事务。
随后,
在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
————————————————
版权声明:本文为CSDN博主「我是机智的鱼油」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29501587/article/details/52135164

幻读

3、幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
例如:
目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。
此时,
事务B插入一条工资也为5000的记录。
这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。

4、提醒
不可重复读的重点是修改:
同样的条件,你读取过的数据,再次读取出来发现值不一样了
幻读的重点在于新增或者删除:
同样的条件,第 1 次和第 2 次读出来的记录数不一样
————————————————
版权声明:本文为CSDN博主「我是机智的鱼油」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29501587/article/details/52135164

SQL中事务隔离_第1张图片

事务的使用:
SQL中事务隔离_第2张图片
自动开启显示事务,首先必须将事务提交设置为手动提交

SQL中事务隔离_第3张图片
一个commit就算是事务提交了。

SQL中事务隔离_第4张图片
设置回滚点。

你可能感兴趣的:(MySQL,sql,数据库,database)