澳门太阳娱乐集团官网-太阳集团太阳娱乐登录

【澳门太阳娱乐集团官网】作业,ACID,隔开等级
分类:数据库

以下内容出自《高性能MySQL》第三版,了解事务的ACID及四种隔离级有助于我们更好的理解事务运作。

在实际的业务场景中,并发读写引出了事务控制的需求。主要关注事务的ACID和隔离性的4个级别。

<1>.事务的概念:
事务是用户定义的一个数据库操作序列,是数据库的逻辑操作单位。这些操作要么全做,要么全不做,是一个不可分割的工作单位。事务和程序是两个概念。一般来说,一个程序中包含多个事务。
<2>. 事务的四个特性ACID:

下面举一个银行应用是解释事务必要性的一个经典例子。假如一个银行的数据库有两张表:支票表(checking)和储蓄表(savings)。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么至少需要三个步骤:

ACID

事务指"一个被视为单一的工作单元的操作序列"。一个良好的事务处理系统,必须具备四个标准特性,即ACID

  1. 原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
  2. 一致性(Consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。
  3. 隔离性(Isolation):通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。针对不同的业务需求,隔离性分为4个级别:读未提交、读已提交、可重复读、串行化。见下
  4. 持久性(Durability):通常来说,一旦事务提交,则其所做的修改会永久保存到数据库(即使系统崩溃,修改的数据也不会丢失)。针对不同的业务需求,持久性也分为多个级别,此处略。
  • 原子性A(Atomicity),事务是数据库的逻辑操作单位。这些操作要么全做,要么全不做。银行转账过程中出现错误,整个事务将回滚。只有事务中的所有部分都成功执行了,才将事务写入磁盘并使变化永久化。
  • 一致性C(Consistency),事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
    一致性与原子性是密切相关的。且两者从概念上容易混淆,我对一致性的理解是,数据库的数据状态符合数据库所描述的业务逻辑和规则。例如以下代码

1、检查支票账户的余额高于或者等于200美元。

隔离性的4个级别

在理解隔离性级别时,很容易混淆“幻读”与“不可重复读”的问题。这里先对4个隔离性级别给出概览;然后分析原理,从实现角度理解各种问题;最后作出总结。

2、从支票账户余额中减去200美元。

概览

关注隔离性的4个级别,包括读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、可序列化(Serializable);及其对应的问题,包括脏读(Dirty Read)、不可重复读(Nonrepeatble Read)、幻读(Phantom Read)。

read(A);

A = A – 100;

write(A);

read(B);

B = B + 100;

write(B);

3、在储蓄帐户余额中增加200美元。

读未提交

读未提交是数据库应保证的最低的隔离性级别:事务中的修改,即使没有提交,对其他事务也都是可见的

读未提交面临脏读的问题:事务可以读取未提交的数据,而该数据可能在未来因回滚而消失。从性能上来说,读未提交不会比其他的级别好太多,但却缺乏其他级别的很多好处。除非真的有非常必要的理由,在实际应用中很少使用。

如果该事务成功执行,没有任何问题。假如执行到read(B)发生了错误,如果没有原子性要求,那么银行系统就会凭空消失100,这也导致了数据库不一致。
但是数据库的不一致不一定是由原子性的破坏造成的,例如:

上述三个步骤的操作必须打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。

读已提交

读已提交满足前面提到的隔离性的简单定义:一个事务所做的修改在最终提交以前,对其他事务是不可见的。换句话说,一旦提交,该事务所作的修改对其他正在进行中的事务就是可见的

狭义上,读已提交解决了脏读的问题。这个级别有时候叫做不可重复读,面临不可重复读的问题:两次执行同样的查询,如果第二次读到了其他事务提交的结果,则会得到不一样的结果

大多数数据库的默认隔离级别都是Read Committed,但MySQL不是。

read(A);

A = A – 100;

write(A);

read(B);

B = B + 50;

write(B);

 

可重复读

在读已提交的基础上,可重复读解决了部分不可重复的问题:同一个事务中多次读取同样记录结果是一致的记录指具体的数据行。

未能解决的那部分称为幻读澳门太阳娱乐集团官网,当某个事务在读取目标范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生第一次读取范围时不存在的幻行(Phantom Row)。需要注意的是,只有插入会产生幻行

MySQL的默认隔离级别是可重复读,有幻读问题。

虽然该事务正常执行,也满足原子性的要求,但是却不满足一致性要求。
所以说原子性的破坏可能导致数据库不一致,但并非是必要条件。因此,事务的原子性与一致性缺一不可。(保证数据库一致性的责任落在了程序员身上。)

可以用START TRANSACTION语句开始一个事务,然后要么使用COMMIT提交将修改的数据持久保存,要么使用ROLLBACK撤销所有的修改。事务SQL的样本如下:

可序列化

可序列化是最高的隔离级别:强制事务序列化执行

可序列化解决了幻读问题。简单来说,可序列化会在目标范围加独占锁,将并发读写相同范围数据的请求序列化。可序列化会导致大量的超时和锁争用问题,因此,实际应用中很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

  • 隔离性I(Isolation),一个事务的执行不能被其他事务干扰。即一个事务内部的操作对并发的其它事务来说是隔离的,并发执行的各个事务之间不能相互干扰。如果有另一个过程根据帐户余额进行相应处理,而它在我们的事务完成前就能看到它造成的变化,那么这个过程的决策可能建立在错误的数据上。
  • 持续性D(Durability),事务一旦提交,它对数据库中数据的改变就是永久性的。接下来的其它操作不应该对其执行结果有任何影响。应该存在一些检查点防止在系统失败时丢失信息。甚至硬件本身失败,系统的状态仍能通过在日志中记录事务完成的任务进行重建。持久性的概念允许开发者认为不管系统以后发生了什么变化,完成的事务是系统永久的部分。
  1. start transaction;

  2. select balance from checking where customer_id = 10233276;

  3. update checking set balance = balance - 200.00 where customer_id = 10233276;

  4. update savings set balance = balance + 200.00 where customer_id = 10233276;

  5. commit;

原理

讨论基于锁的并发控制中,4种隔离性级别的实现原理。重点关注读锁(read lock)、写锁(write lock,或称排它锁)、范围锁(range lock)、锁的持有时间等概念。

<3>.隔离性的四个级别:
有个分析的很好的讲解文章,出自美团点评技术团队:
http://tech.meituan.com/innodb-lock.html

 

读未提交

读未提交的实现:读锁、写锁都在一个原子操作(如select、insert等)完成后立即释放。换句话说,事务作出更新后,不管是否提交,由于已经释放了目标记录的写锁,更新对其他事务就是可见的。

读未提交存在脏读问题,假设操作序列:

  1. 事务1开始
  2. 事务1读取目标记录
  3. 事务2开始
  4. 事务2修改目标记录
  5. 事务1读取目标记录
  6. 事务2回滚
  7. 事务1提交

操作5中,事务1读到了事务2修改但未提交的记录,然后事务2回滚导致修改丢失,也就称事务1读到了“脏数据”,即脏读。

区分目标记录与目标范围(见后文可重复读的实现原理):

  • 目标记录指一个具体的数据行;读锁、写锁只针对目标记录。
  • 目标范围指一个where语句描述的范围;范围锁针对目标范围,见后。

这里做一些简单的说明,以供快速回忆起相关知识
先介绍三种不同的一个事务读取另外一个事务可能修改的数据的“读现象”

ACID表示原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。一个很好的事务处理系统,必须具备这些标准特性:

读已提交

出现脏读的原因是写锁的持有时间过短。读已提交针对这一问题作出了优化:读锁仍然在一个原子操作完成后立即释放;写锁从写操作开始持有,事务提交后释放。事务作出更新前,会先申请目标记录的写锁,并持续持有至事务提交后,释放锁后,更新对其他事务才是可见的。

对于读未提交中的操作序列,操作5发生时,由于事务2持有目标记录的写锁,事务1会阻塞,直到事务2提交释放该写锁,解决了脏读问题。

读已提交还存在不可重复读问题。假设操作序列:

  1. 事务1开始
  2. 事务1读取目标记录
  3. 事务2开始
  4. 事务2修改目标记录
  5. 事务2提交
  6. 事务1修改目标记录
  7. 事务1提交

操作5完成后,事务2的修改对事务1可见,从而操作6中,事务1会读到修改,与操作2的结果不同,因此修改结果无法保证(如根据操作2读取的结果做修改);但是事务1在此之前未对目标记录作出任何修改,因此事务1进行操作6时的状态理应与操作2后一致(回顾事务的一致性要求)。以上即为不可重复读。

不可重复读与脏读之间存在交叉。脏读侧重读到不应存在的数据,不可重复读强调两次相同查询的结果不一样。实际上,可以将描述放宽到“目标记录的状态不符合预期状态”,如本应该不同,却读到了相同。本质上也是由于读已提交实现原理导致的问题。

脏读,一个事务允许读取另外一个事务修改但未提交的数据时,脏读就可能发生。

 

可重复读

解决不可重复读可以使用两种方法:

  1. 悲观策略:串行化
  2. 乐观策略:多版本 + 冲突检测

澳门太阳娱乐集团官网 1

原子性(atomicity)

悲观策略:串行化

“串行化”不需要解释,放弃并发、串行执行当然不存在任何问题。

“串行化”的可重复读实现是:读锁、写锁从读、写操作开始持有,事务提交后释放。与读已提交的实现相比,可重复读延长读锁的持有时间直到事务提交后,在此期间,目标记录无法被修改。

对于读已提交中的操作序列,操作2发生时,事务1开始持有目标记录的读锁,导致事务2的操作4会陷入阻塞,直到事务1提交释放锁。

“串行化”不同于“可序列化”。为了区分,前、后文中均将隔离性级别称为“可序列化”,将此处的悲观策略称为“串行化”。

1.PNG

  一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性

乐观策略:多版本 + 冲突检测

“多版本 + 冲突检测”是更常见的实现方案:多个事务采用多个版本,最后提交时检测是否与当前数据版本冲突,如果冲突则报错提醒,否则成功提交

“多版本 + 冲突检测”的可重复读实现是:事务开始时持有当前数据的快照,读写均不冲突,提交时检测修改的快照与当前数据是否冲突。使用乐观的冲突检测策略代替悲观的锁策略,在中低程度的并发情况下性能更好。

对于读已提交中的操作序列,事务1、2各自持有不同版本的快照,在操作4修改自己版本的目标记录后,操作5提交事务2,检测不冲突(假设没有其他事务),合并到当前数据,当前数据完成修改;然后操作6继续修改自己版本的目标记录,操作7提交事务1,发现与当前数据冲突,给出报错。

不可重复读,在一次事务中,当一行数据获取两遍得到不同的结果表示发生了“不可重复读”。

一致性(consistency)

幻读问题

幻读是一种特殊的不可重复读。

为什么会出现幻读问题呢?

Java的内置锁以对象为单位,RDBMS的锁呢?前面的注释中略有介绍。为了提高并发性能,简单的以数据表、数据库为单位实现锁的性能过低;标准SQL中,读、写锁以记录(数据行)为单位,范围锁以范围(逻辑上的范围,用where描述)为单位。如果没有范围锁,那么显然读、写锁只能“锁”在已存在的记录上。假设操作序列,这次具体一些:

  1. 事务1开始
  2. 事务1统计表内数据的总行数
  3. 事务2开始
  4. 事务2插入一条新纪录
  5. 事务2提交
  6. 事务1利用“旧的总行数+新的数据表内容”计算区分度
  7. 事务1提交

该操作序列是读已提交中操作序列的一个具体实例。因此,可以解决部分不可重复读问题,不能解决的那部分就是幻读了。

以基于锁的“串行化”方案为例(“多版本+并发冲突”同理),假设不使用范围锁,则幻读表现如下:由于事务2插入的记录不获取锁,操作2获取的读锁无法发挥作用,操作5提交事务2后,新记录就对事务1可见了;操作6读取时,事务1认为一致性依然满足,便使用了旧的总行数,并重新读表计算distinct count,却读到了一条意料之外的新纪录,破坏了一致性——好像出现了幻觉一样,这条新纪录就被称为“幻行”,该现象即“幻读”。

澳门太阳娱乐集团官网 2

     数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)

可序列化

对于基于锁的“串行化”方案,可序列化实现:从各操作开始前持有读锁、写锁、范围锁,直到事务提交后释放。对于“多版本 + 冲突检测”方案,可序列化基于更严格的写冲突检测来实现,详见“快照隔离”技术,此处不展开。

范围锁如何解决幻读问题呢?

范围锁是一个逻辑概念上的锁,事务从读、写操作(带显式或隐式where)开始前持有范围锁,直到事务提交后释放。忽略读、写锁,对可重复读中操作序列的影响如下:操作2中事务1获取了目标范围上的范围锁,操作4发现目标范围被锁,陷入阻塞,直到操作7事务提交。

2.PNG

隔离性(isolation)

隔离性级别的总结

各隔离级别解决了不同的问题。"Y"说明存在问题,"-"说明不存在:

隔离级别/问题 脏读 不可重复读 幻读
读未提交 Y Y Y
读已提交 - Y Y
可重复读 - - Y
可序列化 - - -

在基于锁的并发控制中,依靠不同的锁持有时间实现各隔离级别。锁均从操作前开始持有,"S"表示操作结束后释放,"C"表示事务提交后释放:

隔离级别/问题 脏读 不可重复读 幻读
读未提交 S S S
读已提交 C S S
可重复读 C C S
可序列化 C C C

MySQL的默认隔离级别是可重复读,解决了脏读、部分不可重复读问题,有幻读问题。


参考:

  • MySQL ACID及四种隔离级别的解释
  • 事务隔离
  • 数据库的事务隔离与锁机制有什么差别和联系,最近在看,感觉两个很混乱~求解释。?

本文链接:事务的ACID和四个隔离级别
作者:猴子007
出处:https://monkeysayhi.github.io
本文基于知识共享署名-相同方式共享 4.0国际许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名及链接。

在这个例子中,事务2提交成功,因此他对id为1的行的修改就对其他事务可见了。但是事务1在此前已经从这行读到了另外一个“age”的值。在可序列化(SERIALIZABLE)和可重复读的隔离级别,数据库在第二次SELECT请求的时候应该返回事务2更新之前的值。在提交读和未提交读,返回的是更新之后的值,这个现象就是不可重复读。

     通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去200美元。)

幻影读,在事务执行过程中,当两个完全相同的查询语句执行得到不同的结果集。

持久性(durability)

澳门太阳娱乐集团官网 3

  一旦事务提交,则其所做的修改不会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。持久性是个有占模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必,而且不可能有能做到100%的持久性保证的策略。)

3.PNG

 

“幻影读”是不可重复读的一种特殊场景:当事务1两次执行SELECT ... WHERE检索一定范围内数据的操作中间,事务2在这个表中创建了(如INSERT)了一行新数据,这条新数据正好满足事务1的“WHERE”子句。

隔离级别:

事务的四种隔离级别

READ UNCOMMITTED(未提交读)

澳门太阳娱乐集团官网 4

  在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。

4.PNG

READ COMMITTED(提交读)

  大多数数据库系统的默认隔离级别都是READ COMMTTED(但MySQL不是)。READ COMMITTED满足前面提到的隔离性的简单定义:一个事务开始时,只能"看见"已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候叫做不可重复读(nonrepeatble read),因为两次执行同样的查询,可能会得到不一样的结果

REPEATABLE READ(可重复读)

  REPEATABLE READ解决了脏读的问题。该隔离级别保证了在同一个事务中多次读取同样记录结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。

SERIALIZABLE(可串行化)

  SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取每一行数据都加锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

打钩说明该隔离级别还存在这种情况,打X代表该隔离级别已经解决了这种情况:

 澳门太阳娱乐集团官网 5

 

作者:陆炫志

出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111

您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。

本文由澳门太阳娱乐集团官网发布于数据库,转载请注明出处:【澳门太阳娱乐集团官网】作业,ACID,隔开等级

上一篇:总计分页一些sql 下一篇:没有了
猜你喜欢
热门排行
精彩图文