SQL Server 并发控制 第一篇:并发模式和事务

SQL Server 并发控制 第二篇:隔离级别和锁(1)

SQL Server 并发控制 第三篇:隔离级别和行版本(2)

隔离级别定义事务处理数据读取操作的隔离程度,隔离级别控制读操作的行为。在乐观并发模式下,使用行版本化技术,当对数据进行更新时,都会在tempdb中存储该数据行的原始副本,术语叫作行版本(Row Version),把tempdb中存储行版本的空间叫做版本库。在修改操作发生时,SQL Server 创建一个Row Version,将原始数据复制到版本库,Row Version是在修改操作之前已提交的数据。在数据更新期间,如果有其他读操作要访问该数据,那么它将读取到数据的副本,并且不会阻塞写操作。当写操作完成时,释放行版本。

总结,在乐观并发模式下,使用行版本来保证事务的ACID属性,当读操作引用被其他事务更新,但尚未提交的数据时:

  • 对于写操作,对正在更新的数据进行备份,把备份存储到tempdb中。
  • 对于读操作,从tempdb中读取行版本,读取在写操作之前存储的副本。

一,启用基于快照的隔离级别

在乐观并发模式下,有两个基于快照的隔离级别,都使用行版本来维护读操作的一致性:

  • snapshot 隔离级别,简称SI,实现事务级别的数据一致性,在同一个事务中,读取到的数据是一致的,其行为和SERIALIZABLE隔离级别相同。
  • read committed snapshot 隔离级别,简称RCSI,实现语句级别的数据一致性,在同一事务中,可能读取到的数据是不一致的。

1,启用RCSI

在默认的隔离级别Read Committed下,使事务读取Row Versioning数据,只需要把数据库选项READ_COMMITTED_SNAPSHOT设置为ON:

ALTER DATABASE CURRENT
SET READ_COMMITTED_SNAPSHOT ON
WITH NO_WAIT;

当启用READ_COMMITTED_SNAPSHOT选项,意味着把数据库的默认隔离级别设置为RCSI。如果禁用READ_COMMITTED_SNAPSHOT选项,意味着数据库的默认隔离级别是悲观并发模式下的READ COMMITTED隔离级别。

在RCSI隔离级别下,事务有两个特性:

  • 事务使用行版本(Row version)代替加锁,读操作不会阻塞其他事务的写操作;
  • RCSI隔离级别保证语句级别的事务一致性,查询语句只能读取在该语句执行时已经提交的数据,如果在该语句执行时数据更新尚未提交,该语句读取不到。

2,启用SI

使用快照隔离级别,必须分两步来设置,第一步,设置数据库选项 ALLOW_SNAPSHOT_ISOLATION 为 ON,但是该选项没有改变Session-Level的事务隔离级别,第二步,需要修改Session-Level的事务隔离级别为SNAPSHOT,才能使用行版本数据。

step1,设置数据库选项,允许快照隔离级别

ALTER DATABASE CURRENT
SET ALLOW_SNAPSHOT_ISOLATION ON;

step2,把会话的隔离级别设置为SNAPSHOT

把当前Session的隔离级别设置为Snapshot,事务才能访问Row Versioning的数据:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

如果不把会话的隔离级别设置为SNAPSHOT,会话的隔离级别是悲观模式下的READ COMMITTED。

二,基于快照的隔离级别

SQL Server 数据库默认的事务隔离级别是Read Committed,会话默认的隔离级别是数据库默认的隔离级别,即是Read Committed。但是会话默认的隔离级别受到数据库选项 READ_COMMITTED_SNAPSHOT 的影响,该选项影响Read Committed 隔离级别是使用行版本控制事务的读操作,还是使用加共享锁来控制事务的读操作。虽然用户不能修改数据库默认的隔离级别,但是用户可以修改会话默认的隔离级别。

在默认的Read Committed隔离级别下,事务不能读取被其他事务修改,但尚未提交的数据,即只能读取已提交更新的数据:

  • 设置选项READ_COMMITTED_SNAPSHOT为OFF(默认设置),数据库引擎使用Shared Lock阻止其他事务修改当前事务正在读取的数据;当读取被其他事务修改,但尚未提交更新的数据行时,该读操作将被阻塞。
  • 设置选项READ_COMMITTED_SNAPSHOT为ON,数据库引擎使用行版本化(Row Versioning)的数据实现语句级别的一致性,在执行读操作时,事务不会申请共享锁,不会阻塞其他事务的写操作,但只能读取已提交的数据。

1,READ COMMITTED Snapshot隔离级别

READ COMMITTED Snapshot隔离级别(简称RCSI)保证语句级别的读一致性。当数据库选项 READ_COMMITTED_SNAPSHOT 设置为ON,Read Committed隔离级别使用Row Version提供语句级别(Statement-Level)的读一致性,即RCSI隔离级别。

在RCSI下,当一个事务开始运行在RCSI级别下,语句只会看到语句开始时的快照,当重新读取同一个数据时,该数据可能被其他写操作修改,也即是说,在同一个事务中,对同一个数据重复读取,得到的值可能不同。

2,SANPSHOT隔离级别

另外一个基于快照的隔离级别是SANPSHOT隔离级别(简称SI),Snapshot隔离级别使用Row Version 实现事务级别(Transaction-Level)的读一致性。在当前事务开始时,任何读操作,都基于相同的数据snapshot。当读取被其他事务修改的数据行时,读操作只会看到事务开始时的快照,在同一个事务中,对取同一个数据重复读取,得到的值是相同的。

在Snapshot隔离级别下,事务在修改任何数据之前,先将原始数据行复制到tempdb,创建数据行的一个原始版本(Row Version),注意,SQL Server只会复制被修改的数据行,对于未修改的数据行,不会保存行版本数据。后续其他事务的读操作都去读该复制的行版本。在Snapshot隔离级别下,读写操作不会互相阻塞,使用行版本控制能够提高事务的并发性,但是有一个明显的缺点,虽然用户读到的不是脏数据,但是数据可能正在被修改,很快就要过期。如果根据这个过期的数据做数据修改,可能会产生逻辑错误。

3,RCSI和SI的异同

相同点:在snapshot 和 read committed snpshot隔离级别下,事务读取的数据都是已提交的;

不同点:RCSI保证语句级别的读一致性,SI保证事务级别的读一致性:

  • 事务级别的读一致性是指:在事务开始,到事务提交期间,该事务持有数据的一个快照。如果在该事务活动期间,其他事务更新表数据,该事务只会读取快照数据,不会读取到被其他事务更新的数据值;
  • 语句级别的读一致性是指:单个语句(single statement)看到的数据是一致性的;在当前事务活动期间,事务中的语句能够读取到被其他事务提交更新的数据值;例如,在语句stmt1执行时,事务没有提交更新,stmt1看到Reader1的值是2;当语句stmt2执行时,事务提交更新,stmt2看到Reader2的值是3;

三,引用徐海蔚老师的例子,测试隔离级别的行为

snapshot隔离级别不会阻塞其他事务的写操作,该隔离级别忽略数据的修改操作,只读取row versioning的数据,就是说,读取到的是数据修改之前的版本,当snapshot事务尝试修改由其他事务修改的数据时,产生更新冲突,写操作异常终止。

read committed snapshot隔离级别,读取行版本化的已提交数据:

  • 当其他事务未提交更新时,读取行版本化的数据,即读取修改之前的数据值;
  • 当其他事务提交数据更新后,读取修改后数据值;
  • 由于该隔离级别不会申请共享锁,因此不会阻塞其他事务的更新操作;
  • 能够更新由其他事务修改的数据;

四,Snapshot隔离级别

在SNAPSHOT隔离级别下,任何写操作都会将更新之前的数据行保存到tempdb中,读取操作要么从原始数据表中读取数据,要么从tempdb中读取行版本化的数据。Snapshot隔离级别指定:在一个事务中,任何语句读取的数据,是事务一致性的版本。事务一致性是指在事务开始时,在表级别创建数据快照,只能识别其他事务已提交的数据更新。在事务开始之后,当前事务不会识别其他事务执行的数据更新。Sanpshot隔离级别实现事务级别的数据一致性。SQL Server 使用tempdb来存储行版本化(row versioning)的数据,如果数据更新较多,存储的行版本太多,会导致tempdb成为系统瓶颈。

1,在Snapshot隔离级别下,更新操作创建Row Version

一旦启用Snapshot隔离级别,在事务中执行更新操作时,SQL Server将被更新的数据行的原始版本存储在tempdb中,即在tempdb中保存数据行的原始数据,因此,读操作获取取行版本的数据,都是数据被更新之前的值。

2,Snapshot隔离实现事务一致性

Snapshot隔离级别实现事务级别的数据一致性,这意味着,在单个事务中的所有查询语句,看到的是相同版本的数据。在Snapshot隔离级别下,事务在读取数据不需要加行级锁或页级锁,读写操作互不阻塞。

快照隔离级别使得读操作不需要对基础数据行或数据页上施加共享锁,这使其他写事务不会被先前未完成的读事务阻止。修改数据的事务不会阻止读取数据的事务,并且读取数据的事务不会阻止写入数据的事务,这种非阻塞行为显着降低了复杂事务发生死锁的可能性。

3,Snapshot 使用乐观并发模式

Snapshot隔离级别使用乐观并发模式,如果一个Snapshot 事务尝试去提交数据行的更新,但是该数据行已经被其他事务修改,并且修改的时间早于当前事务开始的时间,那么SQL Server将当前事务作为失败者,并回滚其事务操作。乐观并发模式用于冲突较少的环境中,如果应用程序在更新数据时经常发生冲突,Snapshot隔离级别可能不是最好的选择。

参考文档:

Snapshot Isolation in SQL Server

Isolation Levels in the Database Engine

SQL SERVER – Difference Between Read Committed Snapshot and Snapshot Isolation Level

数据库的快照隔离级别(Snapshot Isolation)的更多相关文章

  1. 转:数据库的快照隔离级别(Snapshot Isolation)

    数据库的快照隔离级别(Snapshot Isolation)   隔离级别定义事务处理数据读取操作的隔离程度,在SQL Server中,隔离级别只会影响读操作申请的共享锁(Shared Lock),而 ...

  2. 数据库ACID、隔离级别与MVCC

    首先需要明确事务的概念:一组原子性的SQL查询,如果数据库引擎能够成功的对数据库应用该组查询的全部语句,那么就执行该组语句,否则所有语句都不执行. 事务有ACID四个特性,即: 原子性:一个事务是一个 ...

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

    本文转自https://m.imooc.com/article/details?article_id=17291,感谢作者 1.目的 1.1 合适人群 1.数据库事务特征我只是背过,并没有很深刻的理解 ...

  4. MySQL数据库的事物隔离级别

    一. 查看数据库的事物隔离级别 mysql> show variables like '%isolation'; +-----------------------+--------------- ...

  5. 「DB」数据库事务的隔离级别

    *博客搬家:初版发布于 2017/04/10 00:37    原博客地址:https://my.oschina.net/sunqinwen/blog/875833 数据库事务的隔离级别 讲事务的隔离 ...

  6. Mysql数据库事务的隔离级别和锁的实现原理分析

    Mysql数据库事务的隔离级别和锁的实现原理分析 找到大神了:http://blog.csdn.net/tangkund3218/article/details/51753243 InnoDB使用MV ...

  7. Spring中事务的传播行为,7种事务的传播行为,数据库事务的隔离级别

    Propagation.REQUIRED 代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建 ...

  8. mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理

    一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...

  9. MySQL数据库事务隔离级别(Transaction Isolation Level)

    转自: http://www.cnblogs.com/zemliu/archive/2012/06/17/2552301.html  数据库隔离级别有四种,应用<高性能mysql>一书中的 ...

随机推荐

  1. SQLSERVER将一个文件组的数据移动到另一个文件组

    SQLSERVER将一个文件组的数据移动到另一个文件组 有经验的大侠可以直接忽视这篇文章~ 这个问题有经验的人都知道怎麽做,因为我们公司的数据量不大没有这个需求,也不知道怎麽做实验 今天求助了QQ群里 ...

  2. jQuery UI resizable使用注意事项、实时等比例拉伸及你不知道的技巧

    这篇文章总结的是我在使用resizable插件的过程中,遇到的问题及变通应用的奇思妙想. 一.resizable使用注意事项 以下是我在jsfiddle上写的测试demo:http://jsfiddl ...

  3. C#异步编程(一)

    异步编程简介 前言 本人学习.Net两年有余,是第一次写博客,虽然写的很认真,当毕竟是第一次,肯定会有很多不足之处, 希望大家照顾照顾新人,有错误之处可以指出来,我会虚心接受的. 何谓异步 与同步相对 ...

  4. solr_架构案例【京东站内搜索】(附程序源代码)

    注意事项:首先要保证部署solr服务的Tomcat容器和检索solr服务中数据的Tomcat容器,它们的端口号不能发生冲突,否则web程序是不可能运行起来的. 一:solr服务的端口号.我这里的sol ...

  5. C++中的引用

    一,C++中引用的基础知识 1.引用的基本概念 1.所谓的引用其实就是对变量起“别名”.引用和变量对应得是相同的内存,修改引用的值,变量的值也会改变,和指针类似. 2.引用在定义的时候必须要初始化,初 ...

  6. Maven仓库搭建和配置

    maven在本地搭建仓库的实际需求maven在项目构建过程需要下载一些必要的软件包,这些默认的下载链接都是访问maven的远程中央仓库Central Repo.如果项目中的成员,每次第一次构建的时候都 ...

  7. docker4dotnet #3 在macOS上使用Visual Studio Code和Docker开发asp.net core和mysql应用

    .net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对岸的苹果园越来越茂盛,实在不想再去做一只宅猿了.于是,.net猿决定搭上小鲸鱼的渡轮到苹果园去看 ...

  8. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  9. ASP.NET 5 和Entity Framework 7公告仓库

    ASP.NET 5 有一个公告仓库来介绍ASP.NET 5和 Entity Framework 7的主要变更说明,这个对于日夜更新的项目来说,很多人经常会遇到问题但是不知道去哪里寻找帮助,很多同学在做 ...

  10. 玩转Windows服务系列——给Windows服务添加COM接口

    当我们运行一个Windows服务的时候,一般情况下,我们会选择以非窗口或者非控制台的方式运行,这样,它就只是一个后台程序,没有界面供我们进行交互. 那么当我们想与Windows服务进行实时交互的时候, ...