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. HTML渲染过程详解

    无意中看到寒冬关于前端的九个问题,细细想来我也只是对第一.二.九问有所了解,正好也趁着这个机会梳理一下自己的知识体系.由于本人对http协议以及dns对url的解析问题并不了解,所以这里之探讨url请 ...

  2. Matlab 绘制三维立体图(以地质异常体为例)

    前言:在地球物理勘探,流体空间分布等多种场景中,定位空间点P(x,y,x)的物理属性值Q,并绘制三维空间分布图,对我们洞察空间场景有十分重要的意义. 1. 三维立体图的基本要件: 全空间网格化 网格节 ...

  3. 谈谈一些有趣的CSS题目(八)-- 纯CSS的导航栏Tab切换方案

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  4. SVD奇异值分解的基本原理和运用

    SVD奇异值分解: SVD是一种可靠的正交矩阵分解法.可以把A矩阵分解成U,∑,VT三个矩阵相乘的形式.(Svd(A)=[U*∑*VT],A不必是方阵,U,VT必定是正交阵,S是对角阵<以奇异值 ...

  5. Shell碎碎念

    1. 字符串如何大小写转换 str="This is a Bash Shell script." 1> tr方式 newstr=`tr '[A-Z]' '[a-z]' < ...

  6. ZKWeb网页框架1.3正式发布

    本次更新的内容有 更新引用包版本 Microsoft.AspNetCore.Hosting.Abstractions 1.1.0 Microsoft.AspNetCore.Http.Abstracti ...

  7. pandas基础-Python3

    未完 for examples: example 1: # Code based on Python 3.x # _*_ coding: utf-8 _*_ # __Author: "LEM ...

  8. 灵魂宝石 bzoj 2663

    灵魂宝石(1s 128MB)soulgem [问题描述] "作为你们本体的灵魂,为了能够更好的运用魔法,被赋予了既小巧又安全的外形" 我们知道,魔法少女的生命被存放于一个称为灵魂宝 ...

  9. C#使用GET、POST请求获取结果

    C#使用GET.POST请求获取结果,这里以一个简单的用户登陆为例. 1. 使用GET请求获取结果 1.1 创建LoginHandler.aspx处理页面 protected void Page_Lo ...

  10. 树莓派 基于Web的温度计

    前言:家里的树莓派吃灰很久,于是拿出来做个室内温度展示也不错. 板子是model b型. 使用Python开发,web框架是flask,温度传感器是ds18b20 1 硬件连接 ds18b20的vcc ...