浅谈关系型数据库事务的隔离级别

我们知道在关系型数据库里面事务有四个属性:

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

我们假设现在有A,B不同的两个事务,并且假设事务A在事务B之前启动,在并发执行时会出现的情况无非只有两个状态提交跟未提交,我们排列组合一下得到:

  • A事务启动并提交完成后B事务提交
  • A事务启动并提交完成后B事务未提交
  • A事务启动并未提交B事务提交
  • A事务启动并未提交B事务未提交

进过排序组合后我们得出上面四种情况,而我们只要考虑这四种情况里面的第2,3点。以下我们来分析1,2,3点的情况,大致可划分为A事务提交跟未提交。

而关系型数据库里面对数据的无非是四个基本操作,增,删,改,查。假设现在有A,B两个不同的事务,我们根据事务的状态个四个基本操作组合一下,会得到以下结果。

A:A事务已提交情况

  1. A事务增加数据已提交B事务增加数据
  2. A事务增加数据已提交B事务删除数据
  3. A事务增加数据已提交B事务修改数据
  4. A事务增加数据已提交B事务查询数据
  5. A事务删除数据已提交B事务增加数据
  6. A事务删除数据已提交B事务删除数据
  7. A事务删除数据已提交B事务修改数据
  8. A事务删除数据已提交B事务查询数据
  9. A事务修改数据已提交B事务增加数据
  10. A事务修改数据已提交B事务删除数据
  11. A事务修改数据已提交B事务修改数据
  12. A事务修改数据已提交B事务查询数据
  13. A事务查询数据已提交B事务增加数据
  14. A事务查询数据已提交B事务删除数据
  15. A事务查询数据已提交B事务修改数据
  16. A事务查询数据已提交B事务查询数据

B:A事务未提交情况

  1. A事务增加数据未提交B事务增加数据
  2. A事务增加数据未提交B事务删除数据
  3. A事务增加数据未提交B事务修改数据
  4. A事务增加数据未提交B事务查询数据
  5. A事务删除数据未提交B事务增加数据
  6. A事务删除数据未提交B事务删除数据
  7. A事务删除数据未提交B事务修改数据
  8. A事务删除数据未提交B事务查询数据
  9. A事务修改数据未提交B事务增加数据
  10. A事务修改数据未提交B事务删除数据
  11. A事务修改数据未提交B事务修改数据
  12. A事务修改数据未提交B事务查询数据
  13. A事务查询数据未提交B事务增加数据
  14. A事务查询数据未提交B事务删除数据
  15. A事务查询数据未提交B事务修改数据
  16. A事务查询数据未提交B事务查询数据

以上是A,B事务在并发情况下的所有组合,我们把以上异常情况做一个归纳,设计者们早就替我们总结了各自的概念含义,根据网上相关资料,能得到以下概念:

  • 丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖(A和B事务并发执行,A事务执行更新后,提交;B事务在A事务更新后,B事务结束前也做了对该行数据的更新操作,然后回滚,则两次更新操作都丢失了)。
  • 脏读:一个事务读到另一个事务未提交的更新数据(A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据)。
  • 不可重复读:一个事务读到另一个事务已提交的更新数据(A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了)。
  • 覆盖更新:这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据(即A事务更新数据,然后B事务更新该数据,A事务查询发现自己更新的数据变了)。
  • 虚读(幻读)一个事务读到另一个事务已提交的新插入的数据(A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了)。

事务隔离级别的存在就是为了防止以上现象发生的,根据资料查证:

ANSI/ISO SQL定义的标准隔离级别如下:

可序列化(Serializable)

最高的隔离级别。

在基于锁机制并发控制的DBMS实现可序列化要求在选定对象上的读锁和写锁保持直到事务结束后才能释放。在SELECT 的查询中使用一个“WHERE”子句来描述一个范围时应该获得一个“范围锁(range-locks)”。这种机制可以避免“幻影读(phantom reads)”现象。

当采用不基于锁的并发控制时不用获取锁。但当系统探测到几个并发事务有“写冲突”的时候,只有其中一个是允许提交的。这种机制的详细描述见“‘快照隔离”

可重复读(Repeatable reads)

在可重复读(REPEATABLE READS)隔离级别中,基于锁机制并发控制的DBMS需要对选定对象的读锁(read locks)和写锁(write locks)一直保持到事务结束,但不要求“范围锁(range-locks)”,因此可能会发生“幻影读(phantom reads)”

提交读(Read committed)

在提交读(READ COMMITTED)级别中,基于锁机制并发控制的DBMS需要对选定对象的写锁(write locks)一直保持到事务结束,但是读锁(read locks)在SELECT操作完成后马上释放(因此“不可重复读”现象可能会发生,见下面描述)。和前一种隔离级别一样,也不要求“范围锁(range-locks)”。

简而言之,提交读这种隔离级别保证了读到的任何数据都是提交的数据,避免读到中间的未提交的数据,脏读(dirty reads)。但是不保证事务重新读的时候能读到相同的数据,因为在每次数据读完之后其他事务可以修改刚才读到的数据。

未提交读(Read uncommitted)

未提交读(READ UNCOMMITTED)是最低的隔离级别。允许脏读(dirty reads),事务可以看到其他事务“尚未提交”的修改。

通过比低一级的隔离级别要求更多的限制,高一级的级别提供更强的隔离性。标准允许事务运行在更强的事务隔离级别上。(如在可重复读(REPEATABLE READS)隔离级别上执行提交读(READ COMMITTED)的事务是没有问题的)

另外以上只是数据库层面的隔离级别,在一些应用层面也有针对以上情况定义出相应的隔离级别,例如Spring的隔离级别定义,大家有兴趣可以去查看相关资料。

时间: 2024-10-13 00:57:44

浅谈关系型数据库事务的隔离级别的相关文章

数据库事务的隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复读.幻读这几类问题. √: 可能出现    ×: 不会出现   脏读 不可重复读 幻读 Read uncommitted √ √ √ Read committed × √ √ Repeatable read × × √ Serializable × × × 注意:我们讨论隔离级别的场景,主要是在多个

数据库事务【隔离级别】

为了快速同步数据的需要,我分段执行了两次python脚本,即开启了两个进程同步数据,结果服务器不时报出数据库死锁异常,通过排查代码和数据库日志发现,是由长事务并发引起的.代码中有入账和出账两个方法,里面涉及操作较多,都为其加了事务,抛出异常时可自动回滚,采用数据库(mysql)默认的隔离级别(Repeatable read).提到并发,一般就会想到用同步代码块的方法的处理,但是由于项目是分布式的,共用一个主库,单单在代码加锁是不能保证数据的准确的,那就只能在数据库层面去考虑加锁了.由于数据量暂时

关于数据库事务、隔离级别、锁的理解与整理(转)

数据库事务的ACID特性 1. 事务的四个特性 数据库事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行.一方面,当多个应用程序并发访问数据库时,事务可以在应用程序间提供一个隔离方法,防止互相干扰.另一方面,事务为数据库操作序列提供了一个从失败恢复正常的方法. 事务具有四个特性:原子性(Atomicity).一致性(Consistency).隔离型(Isolation).持久性(Durability),简称ACID. 1.1 原子性(Atom

MySQL数据库事务各隔离级别加锁情况--read uncommitted篇(转)

本文转自https://m.imooc.com/article/details?article_id=17291,感谢作者 1.目的 1.1 合适人群 1.数据库事务特征我只是背过,并没有很深刻的理解. 2.数据库事务的隔离级别只是了解,并没有深刻理解,也没有在实际工作中体验使用过. 3.经常面试被人问起数据库加锁情况,一头雾水,很懵. 4.在网上找过很多博客,有的写得太多没耐心看,有的写得摘抄的定义,泛泛而谈,没有实操更没有讲解. 1.2 关于这篇分享对以上问题的解决 1.实践出真知,如果认真

数据库事务的隔离级别简单总结

数据库中事务的隔离级别有四种,级别由低到高分别为:Read uncommitted.Read committed. Repeatable read和Serializable 四种.这四个级别可以逐个解决脏读.不可重复读.幻读这几个问题. 如果当前隔离级别为Read uncommitted时,可能出现脏读,即可能读到还未提交的临时写数据. 如果当前隔离级别为Read committed时,能够避免脏读,但可能造成不可重复读,即两个事务同时对同一个数据进行修改时,发生的数据一致性和完整性的破坏.大部

MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转)

本文转自https://m.imooc.com/article/details?article_id=17290 感谢作者 上篇记录了我对MySQL 事务 隔离级别read uncommitted的理解.这篇记录我对 MySQL 事务隔离级别 read committed & MVCC 的理解. 前言 可以很负责人的跟大家说,MySQL 中的此隔离级别不单单是通过加锁实现的,实际上还有repeatable read 隔离级别,其实这两个隔离级别效果的实现还需要一个辅助,这个辅助就是MVCC-多版

数据库事务的隔离级别及四大特性

在我们了解数据库隔离级别前先来回顾一下数据库读数据时可能遇到的问题: (1)脏读 一个事务对数据进行更新操作,但还完成,此时另一事务读取该数据,如果此时第一个事务由于操作失败进行了回滚,那么此时另外事务读取的数据就是脏数据. (2)不可重复读 例如事务A在读取某一数据,而事务B立马修改了这个数据并且提交事务给数据库,事务A再次读取该数据就得到了不同的结果,发送了不可重复读. ps:在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主.但在另一些情况下就有可能发

浅谈DB2的四个隔离级别

隔离级别定义用于控制并发事务的行为,它决定在访问数据时数据是如何锁定的.如何与其他进程隔离的. 包括四个级别,级别从高到低: RR(可重复读取) RS(读取稳定性) CS(游标稳定性) UR(未提交的读取) 1.RR隔离级别:在此隔离级别下, DB2会锁住所有相关的纪录. 在一个SQL语句执行期间, 所有执行此语句扫描过的纪录都会被加上相应的锁.在一个SQL语句执行期间,所有执行此语句扫描过的纪录都会被加上相应的锁. 具体的锁的类型还是由操作的类型来决定, 如果是读取,则加共享锁: 如果是更新,

Mysql数据库事务及隔离级别学习测试

参考了这篇文章的一些内容: http://xm-king.iteye.com/blog/770721 我在springdemo库里面建了一个表: CREATE TABLE `tx` ( `id` bigint(11) NOT NULL auto_increment, `num` bigint(11) default 0 COMMENT '用户名', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 CO