当前位置: 首页 > news >正文

SQL Server 中的6种事务隔离级别简单总结

原文: SQL Server 中的6种事务隔离级别简单总结

 

本文出处:http://www.cnblogs.com/wy123/p/7218316.html 
(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)

 


数据库中的事物是具有原子性(Atomicity),一致性(Consistemcy),隔离性(Isolation),持久性(Durability)四个特征。
在上述四个特性中的一致性和隔离性的实现中,是通过锁来实现对相同数据的访问隔离的。
事物的隔离级别又可以影响锁的申请和时间的时机。
因此,不同的事物隔离级别又可以对锁的申请和释放产生不同的影响,因此,在对数据库做事物控制的时候需要了解隔离级别对事物的影响。
SQL Server实现SQL99标准规定的事务的四个隔离级别(未提交读,已提交读,可重复读,序列化)之外,另外增加了两个隔离级别(快照个基于行版本的已提交读隔离级别)。
不同的隔离级别对控制脏读,不可重复读,幻读有一定的控制,也会并发有一定程度的影响,
隔离级别越低,并发性越高,但是产生脏读,不可重复读,幻读等可能性越大;随着事物隔离级别的提交,可以控制脏读,不可重复读,以及幻读的现象,但是并发性也会随之降低。
事物隔离级别和执行计划都可以影响锁(范围)的申请和释放时机,本文暂不讨论执行计划对锁申请的影响,仅在隔离级别上说明锁的申请和释放。
以下简单介绍SQL Server中的六个隔离级别以及每个隔离级别的特征,在此基础上说明每个隔离级别可能存在的问题解决方法。


未提交读

运行当前Session读取其他事务已修改但是尚未提交的数据,也即当前Session可以读取到“脏数据”。
当前Session不会对读取的数据加共享锁。
set transaction isolation level read uncommitted;
或者
select * from table with(nolock)

特点:未提交读是最低的一种隔离级别。
存在的问题:脏读,不一致读,幻读等。


如下是未提交度的存在脏读一种演示(当然也会存在不一致读,幻读等情况)。

   

 


已提交读

set transaction isolation level read committed;
或者
select * from table  默认人就是已提交读
运行当前Session不能读取其他事务已修改但是尚未提交的数据。
如果其他事务提对当前Session读取的数据有修改且尚未提交,当前Session被阻塞。
原因是在以已提交读隔离级别情况下:当前Session会对读取的数据加共享锁,如果遇到读取的数据尚未提交,当前查询被阻塞。

特点:相比为提交读隔离级别,解决了未提交读隔离级别下的读取“脏数据”的问题,
存在的问题:存在不可重复度或者幻读的问题。

 

已提交读隔离级别下存在不可重复读的现象(两次读取的同一行数据结果不一致)

 

 

 不可重复读隔离级别下存在的幻读现象(一个事物中,同样的条件,读到的数据行数不一致)

   

 


可重复读

set transaction isolation level repeatable read;
运行当前Session不能读取其他事务已修改但是尚未提交的数据,并且当前Session运行期间,其他Session不能修改当前Session读取到的数据
也就是说,当前Session运行期间,读取到的数据是被加了共享锁的,所加的共享锁一直保持,直到事务提交的时候才释放。
相比已提交读最大的特点就是事务运行期间,共享锁将一直保持,直到当前Session事务提交,
因此可以保持当前Session读取到的数据不被其他Session修改,所以就不存在两次读取的数据不一致的现象。
可重复读隔离级别解决了不可重复读的问题,但依旧存在幻读的情况。

特点:相比前一种隔离级别,可重复读解决了已提交读隔离级别的不可重复读的问题,也即两次读取的同一行数据是一致的
存在的问题:相比已提交读,依旧存在幻读的问题。

 

  如下是可重复读隔离级别的幻读的现象,也即在同一个事物的两次读取期间,其他事物可以写入当前事物读取的数据(范围)

  


可序列化

当前Session不能读取其他Session已修改但未提交的数据(不允许脏读)
当前Session读取的数据上的共享锁一直保持直到事务提交(可重复读)
当前Session事务提交之前,其他Session不能插入当前Session中读取的键值(解决了幻读的问题)
set transaction isolation level serializable
或者开启事务之后对表加holdlock提示
select * from table with(holdlock) where id = n
可序列化解决了另外一个非常经典的问题,使用update table with(holdlock) 或者select * from table with(xlock,holdlock),并发情况下的“存在则更新不存在则插入”重复插入的问题。
参考:http://www.cnblogs.com/TeyGao/p/6929246.html

可序列化锁定的原理是加范围锁的方式来实现的,当一个Session发起了请求之后,对于当前Session范围内的数据,不管是否存在,都加一个共享锁。
比如在可序列化的隔离级别之下,select * from table with where id>=100 and id<= 120
在Session执行期间,SQL Server会锁定 100<=id<= 120这个范围的数据,不管表中这个区间是否存在数据, 都锁定这个Id的范围,不允许该Id范围的数据写入。
也即100<=id<= 120这个范围被所锁定(无法增加删除或者修改这个范围的数据)

 

可序列化隔离级别解决了幻读的问题,也就是说,当前事物的两次读中间,其他Session对当前Session读取数据范围之内的数据修改的时候,会被阻塞,直到当前事物提交。

   

 

 

基于行版本控制的隔离级别

  默认隔离级别,也即已提交读隔离级别下,存在一个明显的问题就是写会阻塞读,也就是说,一个写数据的事物未提交之前,会阻塞其他事物对当前操作数据的读取,直到当前写事物的操作提交。
  基于行版本控制的已提交读隔离级别下,写不会阻塞读,写数据的事物未提交之前,会将修改的数据之前的版本,写入临时数据库,
  读数据的事物在读取的时候,发现要读取的数据被修改,会转向临时库中读取出来一个写事物修改数据之前的版本,这样可以在一定程度上提高并发性(当然临时库会承担一定的压力)。
  SQL Server有两种基于行版本控制的隔离级别:快照隔离级别(snapshot)和基于行版本控制的已提交读隔离级别(read_committed_snapshot)
     两种行版本控制分别要基于数据级别开启allow_snapshot_isolation和read_committed_snapshot

(1)快照隔离级别(snapshot)

数据库级别设置快照隔离级别
alter database Test set allow_snapshot_isolation on;

 

 Session级别设置快照隔离级别:set transaction isolation level snapshot

 

快照隔离级别最大的特点是,当前Session读取其他事物修改的数据的时候,不会被阻塞,读取的是其他事物已经修改,但是尚未提交的数据
但是当前事物尝试修改“在其他其他事物中提交修改之后的数据”,会报错(快照隔离事务由于更新冲突已终止)。
具体过程如下,从时间的维度来看,步骤如下
1)Session2 开启事物,修改Id =1的数据,暂不提交
2)Session1 读取id=1的数据,不会被阻塞,读取到的是Session2修改之前的数据的版本
3)Session2修改Id =1的数据之后,事物提交
4)Session1尝试修改Id=1的数据,报错

  

  实际操作上看,如下

 

(2)基于行版本控制的已提交读隔离级别(read_committed_snapshot)

数据库级别设置为基于行版本控制的已提交读隔离级
alter database Test set read_committed_snapshot on;
go


--将当前事物设置为已提交读快照隔离级别
set transaction isolation level read committed

快照隔离级别最大的特点是,当前Session读取其他事物修改的数据的时候,不会被阻塞,读取的是其他事物已经修改,但是尚未提交的数据
与快照隔离级别相对,当前Session尝试修改“在其他其他Session中提交修改之后的数据”,可以成功提交。
具体过程如下,从时间的维度来看,步骤如下
1)Session2 开启事物,修改Id =1的数据,暂不提交
2)Session1 读取id=1的数据,不会被阻塞,读取到的是Session2修改之前的数据的版本
3)Session2修改Id =1的数据之后,事物提交
4)Session1尝试修改Id=1的数据,成功提交,

  基于行版本控制的已提交读隔离级别最大的特点是,当前读取的数据是,其他Session已修改尚未提交之前的版本,但是当前事物尝试修改时,可以成功提交
  这样一来,就忽略掉了当前事物运行期间,其他事物修改且提交的那个版本的数据,有点绕,需要慢慢理解。

  行版本控制的已提交读隔离级别的问题也很明显,当前Session读取数据的时候,是其他事物修改之前的版本,当前Session对读取到的数据可以在其他事物提价之前的版本上执行修改,
  而忽略了当前Session在读和写的间隔期间,其他Session修改并且提交事物的影响,为此可能会产生一定程度的影响。

 

   从时间维度上看如下图所示

 

 

具体执行现象如下:
存在的问题就是,Session1第一次读取的时候,读取的Id = 1数据的那么是AAA,实际上此时其他Session2已经将Id = 1的那么修改为了Update_AAA,
随后Session2事物提交,当前Session执行修改的时候,忽略了Session2修改后的数据,可以直接将数据修改为AAA+++
需要注意的是,Session1修改成功的前提是Session2的事物提交,如果Session2修改事物没有提交,Session1的修改操作被阻塞。

截图中第一行的备注没有修改过来,应该是快照已提价读隔离级别

   

  

 总结:

  本文简单阐述了SQL Server中的几种隔离级别,SQL Server实现了SQL99定义的四个标准隔离级别,并且额外实现了两个快照隔离级别。
  需要说明的是,不同的DBMS的默认隔离级别和对隔离级别的实现是不完全一样的,也不一定是完全按照SQL99定义的四个标准隔离级别来实现的,
  因此在做事物控制的时候,需要了解具体的隔离级别以及具体特性。

相关文章:

  • 《区块链原理、设计与应用》一3.1 应用场景概览
  • json数据导出excel
  • spring cloud 学习(9) - turbine stream无法在eureka注册的解决办法
  • 什么是Ubuntu的云计算?
  • 高危预警!移动设备安全面临的5大新型威胁
  • IOCP vs EPOLL
  • 体验Windows Mobile 6.5 (模拟器)
  • 这是要逆天么,看我控制台程序玩Microsoft XPS Document 打印
  • Spring Cloud中负载均衡器概览
  • 文件特殊权限:SUID,SGID,SBIT
  • 11.03 在外链接中用OR逻辑
  • 将文件名从1变为000001
  • 重构之美-跨越Web标准,触碰语义网[分离:通用也许是个美丽陷阱]
  • shell脚本(1)
  • 笔记-Kotlin学习
  • CSS 提示工具(Tooltip)
  • C语言笔记(第一章:C语言编程)
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • javascript从右向左截取指定位数字符的3种方法
  • Linux后台研发超实用命令总结
  • python 装饰器(一)
  • Quartz初级教程
  • React Transition Group -- Transition 组件
  • Spring Cloud Feign的两种使用姿势
  • webpack+react项目初体验——记录我的webpack环境配置
  • 安装python包到指定虚拟环境
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 成为一名优秀的Developer的书单
  • 关于List、List?、ListObject的区别
  • 温故知新之javascript面向对象
  • 我有几个粽子,和一个故事
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序01:wepy框架整合iview webapp UI
  • 新手搭建网站的主要流程
  • 选择阿里云数据库HBase版十大理由
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • #pragma once
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • $forceUpdate()函数
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (四) 虚拟摄像头vivi体验
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)可以带来幸福的一本书
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .NET BackgroundWorker
  • .NET NPOI导出Excel详解