Web开发必知的八种隔离级别
作者
James Leigh
译者
曹如进
发布于
2009年11月11日 上午2时18分
Architecture
主题
性能和可伸缩性
,
事务处理
ACID
性质是数据库理论中的奠基石,它定义了一个理论上可靠数据库所必须具备的四个性质:原子性,一致性,隔离性和持久性。虽然这四个性质都很重要,但是隔离性
最为灵活。大部分数据库都提供了一些可供选择的隔离级别,且现在许多库都增加了附加层来创建颗粒度更细的隔离。隔离级别应用范围如此之广主要是因为放宽隔
离约束往往会使得可扩展性和性能提高几个数量级。
串行一致性是可用的最古老最高的隔离级别之一,它之所以倍受青睐是因为其提供的简单编程模型,即每次仅能有一个事务对给定的资源进行操作,这就避免
了很多潜在的资源问题。尽管如此,大部分应用程序(尤其是Web应用程序)都不采用这种级别非常高的隔离,因为从终端用户的角度来看这是不切实际的-任何
一个拥有大量用户群的应用程序在访问共享资源时都将会有几分钟的延迟,而这会使得用户量迅速减少。弱一致性和最终一致性在大规模分布式数据源中,例如
Web中,随处可见。好几个成功的大型Web应用(例如,eBay和Amazon)都显示出乐观的(optimistic)弱一致性要比传统悲观的
(pessimistic)机制在扩展性方面好得多。本文将一窥八种不同的隔离级别。学会适当的放宽数据一致性的约束,你可以在自己的应用程序中使用这八
种隔离级别来获得更好的性能和可扩展性。
并发控制的主要目标是为了确保事务被隔离且不会影响到其他事务。要达到高级别的隔离需以牺牲性能为代价。并发控制可以用悲观或者乐观的机制来实现。
大部分关系型数据库都使用了悲观机制来实现写入优化。悲观机制采用了锁,通过使用锁它可以阻塞一些操作或者进行某些形式的冲突检测。当一个表格,页面或是
行被修改后,悲观机制中的锁可以用来阻塞其他潜在的访问修改资源的事务。然而,乐观机制并不采用任何锁,它仅仅依赖于冲突检测来维护事务隔离。乐观机制采
用的冲突检测可以允许所有的读操作,并在事务结束时检验其一致性。如果检测到冲突,那么事务会进行回滚或重做。大部分web服务器都是读入优化,因此使用
了乐观机制。通过允许所有的读入操作,乐观机制既可以保证很高的读写吞吐量,也可以在资源不是一直改变的情况下保证数据的一致性。
下面列出的隔离级别是用来帮助Web开发人员更好的理解他们编程模型中放置的约束,帮助系统架构师和开发人员共同讨论如何在保持必要的数据完整性的同时选择最有效的隔离级别。它们按照最少隔离(未提交读)到最多隔离(串行化)的顺序列出。
1、未提交读(Read Uncommitted)
未提交读隔离级别需要事务间很少的隔离。每一个读操作都能看到事务中等待的写操作(脏读)。然而已经提交的写操作必须要有一个串行顺序来防止脏写。
悲观机制会阻塞有冲突的写操作直到其他写操作已经被提交或已经回滚。乐观机制不会锁住这些操作,它会允许所有的操作都通过。如果一个连接进行了回滚,那么
接下来修改同一块数据的其他操作也会被回滚。在这种级别中,共享缓冲可以不加验证的进行使用。这种隔离级别最好在不需要事务(比如只读的数据集),或者事
务只在独占数据库时才修改的情况下使用。
例子
:一个只在离线情况下更新的档案数据库,或者不在事务中使用的审核/登陆(audit/logging)表。
2、已提交读(Read Committed)
已提交读可以读取系统中任何已经提交的状态,并且可以不加验证(混合状态)的进行缓冲,只需当前连接中发生的改变能够反映到结果中即可。悲观机制将
其实现为单调视图。乐观事务则隔离存储所有的改动,使得它们直到提交后才可用。读已提交使用一个非常乐观的机制,它推迟写入所有的变化直到事务被提交为
止。这种形式的乐观隔离可以在不阻塞读操作的情况下实现复杂的写入操作,并且它没有验证模式。共享缓冲只能在已提交的状态中使用。这种隔离级别最好在结果
可以使用旧值,且事务只能用于写入操作的情况下使用。
例子
:一个不必显示当前最新帖子的在线论坛,且它的帖子间数据不相冲突。
3、单调视图(Monotonic View )
单调视图是对读已提交的一个扩展,它其中的事务在执行时会观察数据库中一个单调上升的状态。在这种级别中,如果有明显的写入事务,那么悲观事务会在
读入操作中被阻塞。乐观事务会像在读已提交中一样操作,隔离保存所有的改动,并且会验证它们的缓冲以确保其仍然合法。这种级别可以定期地同步数据库副本,
且最好在不需要事务或者仅存在写操作事务的情况下使用。
例子
:一个仅能由一个人来修改的用户偏好表。
4、快照读取(Snapshot Reads)
快照读取扩展了单调视图,它可以保证查询结果都能反映到数据库一致的快照中。悲观机制会在读操作时阻碍其他影响结果的写入操作。乐观机制则允许其他
的写入操作,并通知读取事务某部分已经发生改变并进行回滚。想要实现一个乐观机制,必须在读操作结束之前验证是否有什么并行的写入操作修改了结果,如果有
的话,那么结果可能会重做或回滚。这个检验过程可能只是简单的检查同一张表中是否出现了写入操作,或者只是检查改动的查询结果。乐观隔离级别可以很轻松地
检测出冲突,并且在允许并发读入操作的过程中,支持写入操作。这种级别只要能够读取到快照,便可以定期地同步数据库副本。最好在写入操作很少,不想与读入
操作冲突,且查询结果需要一致性的时候使用这种隔离级别。
例子
::一个查询比修改频繁,且只保留最新值的货币换位表或者查询表。
5、游标稳定性(Cursor Stability)
游标稳定性隔离扩展了读已提交,并且是许多关系型数据默认的隔离级别。在这种隔离级别中,悲观事务如果在一个单独的语句中执行的话,必须得指定它将
修改的记录。这通常可以在"SELECT"查询后附加“FOR
UPDATE”关键字来实现。在这种情况下,其他冲突的读写悲观事务都将被阻塞直到该事务结束为止。乐观事务会跟踪提交时被验证的所有修改记录/实体的版
本号。这是一种很流行的乐观隔离级别,因此被所有的主流对象关系映射库支持。在Java持久性API中,可以使用FLUSH_ON_COMMIT(尽管查
询可能不影响本地改动)来接近达到这种级别,且如果检测到冲突的话,可以抛出OptimisticLockException
异常。这种隔离也同样可以用在HTTP头域的If-Match或者
If-Unmodified-Since中,它可以用来在更新前对比上一个资源的版本或者时间戳。这种级别最好在实体由外部信息(不从数据库中读取)更
改,或者改动不会彼此覆盖的情况下使用。
例子
:一个共享的公司目录或者一个wiki。
6、可重复读取(Repeatable Read)
可重复读取级别扩展了游标稳定性,它保证事务内的任何数据在事务过程中都不会被修改或者移除。悲观事务需要读取所有记录上的锁,并阻塞其他服务来修
改这些记录。乐观事务则会跟踪所有的记录或者实体,并检查它们是否在提交时被修改过。这种级别最好在实体状态能够影响其他实体,或者事务由读写操作构成的
情况下使用。
例子
:一个订单跟踪数据库,它从一个实体中读取值并用它来计算其他的实体值。
7、快照隔离(Snapshot Isolation)
快照隔离扩展了快照读取和可重复读取,它保证事务中所有进行的读操作都能看到数据库中一致的快照。事务执行的的任何读操作都会有相同的结果,而不管
它们在事务中执行的早晚。这和可重复读取不同,因为快照隔离能够防止幻读(查询结果不断变化)。许多关系型数据库采用多版本并发控制(也可以叫做
SERIALIZABLE)来支持这种级别,实现方法是通过锁和冲突检测的组合。在这种级别中,考虑到它可能与悲观机制或者乐观机制相冲突,因此事务一定
要做好回滚的准备。悲观机制会通过锁住资源来尝试减少冲突的机会,但是必须在事务提交后将这些改动合并。乐观机制也会使用多版本并发控制,但是它不会阻塞
其他可能产生潜在冲突操作的事务,反而是将冲突的事务进行回滚。这种级别的隔离最好在事务可以读取和修改多个记录的情况下使用。
例子
:一个基于系统状态规则的工作流系统。
8、可串行性(Serializability)
串行性是快照隔离的扩展,它要求所有的事务都必须一个接着一个的出现,就好比它们被串行化过一样。悲观机制需要锁住所有评估过的查询,以防止写入操
作影响这些结果。而乐观机制则跟踪所有评估过的查询,并在事务结束时使用一个后向验证或前向验证的模式来检查是否有并行写入操作影响了并行读入操作,如果
有的话,它会将冲突事务外的所有事务进行回滚。在这种隔离级别中,任何提交事务都不会改变系统的表征状态。最好在需要完整数据一致性的情况下使用这个级别
的隔离。
例子
:一个进行范围查询来计算新值的账目系统。
总结
下面是本文提到的隔离级别的汇总表,它可以帮助你找到最适合你应用程序的级别。
事务在不同隔离级别中可能的冲突类型:
|
脏写
|
脏读 |
混合状态 |
不一致读 |
覆写 |
不可重复
|
幻读
|
不一致性
|
未提交读
|
不可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
已提交读
|
不可以 |
不可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
单调视图
|
不可以 |
不可以 |
不可以 |
可以 |
可以 |
可以 |
可以 |
可以 |
快照读取
|
不可以 |
不可以 |
不可以 |
不可以d
|
可以 |
可以 |
可以 |
可以 |
游标稳定性
|
不可以 |
不可以 |
可以 |
可以 |
不可以 |
可以 |
可以 |
可以 |
可重复读取
|
不可以 |
不可以 |
可以 |
可以 |
不可以 |
不可以 |
可以 |
可以 |
快照隔离
|
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
可以 |
可串行性
|
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不可以 |
不同隔离级别的最佳前提:
|
缓冲 |
数据同步 |
乐观冲突模式
|
建议操作
|
例子 |
未提交读 |
允许缓冲
|
间歇的 |
检测脏写
|
不能并发读写
|
档案
|
已提交读 |
允许缓冲
|
间歇的 |
没有冲突检测
|
单调的读/写
|
Web论坛
|
单调视图 |
必须被验证
|
周期的
|
没有冲突检测 |
组合读入
|
用户偏好
|
快照读取 |
必须被验证
|
周期的
|
对比读入与修改内容
|
一致性读入 |
查询表
|
游标稳定性 |
允许缓冲
|
间歇的 |
对比修改的实体版本
|
CRUD服务
|
目录
|
可重复读取 |
允许缓冲
|
间歇的 |
对比读入的实体版本 |
读/写实体
|
订单跟踪
|
快照隔离 |
必须被验证
|
周期的
|
对比读入的实体版本 |
同步实体
|
工作流
|
可串行性 |
必须被验证
|
完整同步
|
对比查询与修改内容
|
完善数据一致性
|
账目
|
数据一致性在数据库应用程序中至关重要-它允许开发者在分布式环境下使用数据。尽管强一致性级别如可串行性提供了一个简单的编程模型,但是它们会导
致开销
过大,操作阻塞或者事务回滚,这对于很多应用程序来说都是不必要的。如果有其他问题的话,可以使用更加适当的隔离级别来帮助开发人员和系统架构师,让他们
在保持性能和开销平衡的前提下更好的理解数据一致性的需求。
分享到:
相关推荐
在Web开发中,事务处理是关键,Oracle支持ACID(原子性、一致性、隔离性和持久性)属性,确保数据的一致性。 七、备份与恢复 定期备份数据库,防止数据丢失。Oracle提供物理备份(如RMAN)和逻辑备份(如EXPDP/...
### Web开发安全规范知识点 #### 一、概述 **背景简介** 随着互联网的普及和Web技术的快速发展,Web安全面临的挑战日益严峻。黑客攻击技术变得越来越成熟和普遍,针对Web应用的攻击事件频繁发生,使得Web安全风险...
《夏帮贵《Java web开发完全掌握》示例源代码(6-9章)》是针对Java Web开发的一份重要参考资料,它包含了作者夏帮贵在书籍中讲解的关键概念和实践示例。Java Web开发是构建基于Java技术的互联网应用程序的过程,...
《php和mysql web开发(原书第4版)》:开发人员专业技术丛书。 目录 读者反馈 译者序 前言 作者简介 第一篇 使用PHP 第1章 PHP快速入门教程 1.1 开始之前:了解PHP 1.2 创建一个示例应用:Bob汽车零部件商店 ...
4. **事务与并发控制**:讨论事务处理、并发问题和隔离级别,确保数据的一致性和完整性。 5. **存储引擎**:介绍InnoDB和MyISAM等不同存储引擎的特性和选择,以及MySQL的新特性如JSON支持和窗口函数。 6. **MySQL...
2.7.2 知道何时读完文件:feof() 2.7.3 每次读取一行数据:fgets()、fgetss()和fgetcsv() 2.7.4 读取整个文件:readfile()、fpassthru()和file() 2.7.5 读取一个字符:fgetc() 2.7.6 读取任意长度:fread() 2.8 使用...
在IT行业中,多租户架构是一种常见的设计模式,特别是在云服务和SaaS应用中,它允许服务提供商为多个客户提供独立的、隔离的数据环境。Mybatis-Plus是一个强大的Mybatis扩展,它提供了许多便利功能,如简化 CRUD ...
这通常是通过引入一个中间层,这个中间层可以处理系统级别的交互,如文件操作、系统通知,以及与硬件的通信,同时确保Web应用的执行环境与操作系统隔离,从而保证安全性。 基于标签“前端”和“安全”,我们可以...
尽管部分内容似乎是一些重复的购买链接,并没有提供具体的Java Web开发信息,但我们可以基于标题“Java_Web整合开发 王者归来008”以及描述“一款学习java web开发的非常好的教材,一款web开发强人的技术词典”,来...
8. **MVC(Model-View-Controller)**架构:这是Web开发中常见的设计模式,笔记会讲解如何在J2EE中实现。 9. **部署描述符**:如web.xml和ejb-jar.xml,是配置应用的重要文件,笔记会解释其结构和用途。 10. **...
Python Web开发是一个广阔而充满活力的领域,涵盖了各种框架、库和工具,这些工具极大地提升了开发者的工作效率。本文将深入探讨一些常用的Python Web开发工具,它们在构建高效、可扩展和用户友好的Web应用程序中...
- **选择合适的事务隔离级别**:较低的隔离级别可以提供更好的性能,但会增加数据不一致的风险。 - **异步处理**:对于非关键操作,可以通过异步方式处理,以减少事务处理的时间。 - **缓存技术**:利用缓存减少对...
- **事务管理**:了解Spring如何支持声明式事务管理,以及在不同数据源上的事务隔离级别和回滚策略。 - **Spring Boot**:虽然不是原始的Spring包,但Spring Boot是基于Spring框架的快速开发工具,它简化了配置并...
- **事务处理**:ACID属性,事务的隔离级别。 - **视图与存储过程**:视图的创建及用途,存储过程的设计与调用。 ##### 3. Web应用安全 - **输入验证**:用户输入的数据清理与验证。 - **SQL注入防护**:使用预处理...
【描述】:本课程设计项目采用SpringBoot框架,旨在提供一个完整的宾馆客房预订系统的实现,让学生深入理解和掌握Java Web开发技术。通过这个项目,你可以学习到如何构建一个实际的、功能完备的Web应用,包括用户...
在插入新用户信息的方法`insertNewCustomer`上,需添加事务注解`@Transactional`,指定隔离级别为`Isolation.REPEATABLE_READ`,传播行为为`Propagation.REQUIRED`,并且设置`readOnly`为`false`,以确保事务的完整...
《php和mysql web开发(原书第4版)》:开发人员专业技术丛书。 目录 读者反馈 译者序 前言 作者简介 第一篇 使用PHP 第1章 PHP快速入门教程 1.1 开始之前:了解PHP 1.2 创建一个示例应用:Bob汽车零部件商店 ...
+ 事务的隔离及默认的隔离级别 + 左联、右联的区别及查出来的数据的形式 * Redis: + 数据类型,及工作中常用的数据类型及基础的命令 + 雪崩、击穿、穿透及解决方案 + 如何用Python实现类似与Redis集群的效果...