sql server 锁与事务拨云见日(中)
一.事务的概述
上一章节里,重点讲到了锁,以及锁与事务的关系。离上篇发布时间好几天了,每天利用一点空闲时间还真是要坚持。听《明朝那些事儿》中讲到"人与人最小的差距是聪明,人与人最大的差距是坚持"很经典的一句话一直记得。这篇重点围绕事务来开展。涉及的知识点包括:事务的概述,事务并发控制模型,并发产生的负面影响,事务隔离级别以及不同的表现。本章多以文字描述为主,没有多少代码量,重点是阐述不同隔离级别的不同表现,在以后的业务中,涉及到事务时,本文可以用来做个参考。
1.1 事务ACID
事务作为一个逻辑工作单元执行一系列的操作,它包括四个属性:原子性、一致性、隔离性和持久性 (ACID) 属性, 只有这样才能成为一个事务。
原子性:当一个事务被当作一个单独的工作单元时,不管事务内有什么,都是一个整体。对于其数据修改,要么全都执行,要么全都不执行。
一致性:事务在完成时,必须使所有的数据都保持一个逻辑一致状态。
隔离性:并发事务所做的修改必须与其他并发事务所做的修改隔离。 事务能识别数据所处的状态,要么是另一并发事务修改它之前的状态,要么是并发事务修改它之后的状态。
持久性:一但事务完全,它的效果是永久存于系统的。该修改即使出现系统故障也将一直保持。 SQL Server 2014和更高版本启用延迟的持久事务。
1.2 事务的操作模式有几下几种:
自动提交事务:每条单独的语句都是一个事务。
显式事务:每个事务均以 BEGIN TRANSACTION 语句显式开始,以 COMMIT 或 ROLLBACK 语句显式结束。
隐式事务:在前一个事务完成时新事务隐式启动,但每个事务仍以 COMMIT 或 ROLLBACK 语句显式完成。
批处理级事务:只能应用于多个活动结果集 (MARS),在 MARS 会话中启动的 Transact-SQL 显式或隐式事务变为批处理级事务。在sql server 2000 必须对每个 SqlCommand 对象使用独立的 SqlConnection 对象。但是 SQL Server 2005 启用了 MARS,可以共用一个SqlConnection 对象。
本章重点讲到显式事务的隔离级别
二. 事务并发模型
2.1 并发访问是指:多用户同时访问一种资源被视为并发访问资源。 并发数据访问需要某些机制,以防止多个用户试图修改其他用户正在使用的资源时产生负面影响,机制就是下面讲的事务隔离级别。处于活动状态而不互相干涉的并发用户数据越多,并发性就越好。当一个正在修改数据的用户阻止了其他用户读取数据,或者当一个正在读取数据的用户阻止了其它用户修改数据时,并发性就降低了。
2.2 并发类型
在sqlserver里数据库系统可以采用两种方式来管理并发数据访问:乐观并发控制和悲观并发控制,在sql server 2000以前只有悲观并发。乐观并发控制是一种称为行版本控制(row versioning)的技术支持。这二种技术并发控制的区别在于:是在冲突发生前进行防止,还是在发生后采用某种方法来处理冲突。
悲观并发控制
在悲观并发中,sql server是获取锁来阻塞对于其它用户正在使用数据的访问。 用户操作的读与写之间是会互相阻塞的。
乐观并发控制
乐观并发控制默认采用行版本控制使其它用户能够看到修改操作发生以前的数据状态,旧版本数据行会保存下来。因些读取数据不会受到其它用户正对该数据进行修改操作的影响,换言之修改数据不会受到其它用户正对该数据进行读取影响。 因为读取用户访问的数据行是一个被保存过的版本。 用户读与写之间不会互相阻塞,但写与写还是会发生阻塞。
2.3 事务并发带来的负面影响
修改数据的用户会影响同时读取或修改相同数据的其他用户。 即这些用户可以并发访问数据。 如果数据存储系统没有并发控制,则用户可能会看到以下负面影响:
并发影响 |
定义 |
丢失更新 |
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。 每个事务都不知道其他事务的存在。 最后的更新 将覆盖由其他事务所做的更新,这将导致数据丢失。 |
脏读 |
当一个用户修改了数据但尚未提交修改,而另一个正在读取的用户会读到这个修改从而导致不一致的状态发生。 |
不可重复读 |
一个用户在同一个事务中分别以两个读操作间隔读取相同资源时可能会得到不同的值。 |
虚拟读取(幻影) |
一个事务里执行两个相同的查询,但第二个查询返回的行集合是不同的,此时就会发生虚拟读取。这种情况发生在where 查询中,比如 where count(1)<10。 同一个事务中多次使用相同的条件查询,select操作返回不同数据的结果集。 |
三.事务隔离级别
在sql server 2005及以上 支持五种隔离级别来控制“读”操作的行为,其中有三个是悲观并发模式,一个是乐观并发模式,剩下一个存在两种模式。 下面介绍隔离级别从允许的并发负作用(例如脏读或虚拟读取)的角度进行描述。
隔离级别 |
定义 |
未提交读 |
隔离事务的最低级别,未提交读不会发出共享锁,允许脏读,一个事务可能看见其他事务所做的尚未提交的更改。未提交读不会发出共享锁. 该项的作用与与SELECT表上加NOLOCK相同。 |
已提交读 |
一个事务不能读取其它事务修改但未提交的数据,避免了脏读。事务内语句运行完后便会释放共享锁,而不是等到事务提交的时候。 这是数据库引擎默认级别。 |
可重复读 |
事务内查询语句运行完后不会释放共享锁,而是等到事务提交后.其它事务不能修改,删除,但可以插入新数据。 因为不是范围锁,可能发生虚拟读取。 |
可序列化SERIALIZABLE |
隔离事务的最高级别,事务之间完全隔离。 阻止其它事务删除或插入任何行。 相当于SELECT上加HOLDLOCK相同, SELECT 操作使用 WHERE 子句时获取范围锁,主要为了避免虚拟读取。 |
已提交读 快照隔离 |
当 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON 时,已提交读隔离使用行版本控制提供语句级读取一致性。 读取操作只需要 SCH-S 表级别的锁,不需要页锁或行锁。 使用行版本控制为每个语句提供一个在事务上一致的数据快照,因为该数据在语句开始时就存在。 |
快照隔离 |
快照隔离级别使用行版本控制来提供事务级别的读取一致性。 读取操作不获取页锁或行锁,只获取 SCH-S 表锁。 读取其他事务修改的行时,读取操作将检索启动事务时存在的行的版本。 当 ALLOW_SNAPSHOT_ISOLATION 数据库选项设置为 ON 时,只能对数据库使用快照隔离。 默认情况下,用户数据库的此选项设置为 OFF。 |
sql server主要是通过共享锁申请和释放机制的不同处理,来实现不同的事务隔离级别。不同隔离级别允许的并发副作用如下:
隔离级别 | 脏读 | 不可重复读 | 幻影读 | 并发控制模型 |
未提交读 | 是 | 是 | 是 | 悲观 |
已提交读 | 否 | 是 | 是 | 悲观 |
已提交读快照 | 否 | 是 | 是 | 乐观 |
可重复读 | 否 | 否 | 是 | 悲观 |
快照 | 否 | 否 | 否 | 乐观 |
可串行化 | 否 | 否 | 否 | 悲观 |
不同隔离级别对共享锁的不同处理方式如下:
隔离级别 | 是否申请共享锁 | 何时释放 | 有无范围锁 |
未提交读 | 否 | 无 | |
已提交读 | 是 | 当前语句做完时 | 无 |
可重复读 | 是 | 事务提交时 | 无 |
可序列化 | 是 | 事务提交时 | 无 |
四.事务隔离不同表现
设置未提交读
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
设置提交读
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
设置可重复读
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
4.1 未提交读和提交读与其它事务并发,的区别如下表格:
未提交读 |
提交读 |
其它事务 |
SELECT Model FROM Product WHERE SID=10905 显示model 值为test |
SELECT Model FROM Product WHERE SID=10905 显示model 值为test |
begin tran update product set model='test1' where SID=10905 |
SET TRANSACTION ISOLATION |
SET TRANSACTION ISOLATION LEVEL READ COMMITTED |
这个事务将model值改为test1. 此时修改的X锁未释放 |
SELECT Model FROM Product WHERE SID=10905 显示model值为test1,但这并不正确, 因为其它事务还没有提交。没有获取共享锁 |
SELECT Model FROM Product WHERE SID=10905 查询被阻塞 申请获取共享锁时失败,因为X锁未释放 |
|
阻塞消失,得到的值还是test |
rollback tran 这里事务回滚了x锁释放,值还是test |
4.2 已提交读和可重复读与其它事务并发,的区别如下表格:
已提交读 |
可重复读 | 其它事务 |
SET TRANSACTION ISOLATION |
SET TRANSACTION ISOLATION |
|
begin tran 另一事务是已提交读时,这里事务修改成功 另一事务是可重复读时,这里事务修改阻塞 |
||
SELECT Model FROM Product |
SELECT Model FROM Product |
|
commit tran 这里就是一个事务里多次读取同一值 |
commit tran |
未完...sql server 锁与事务拨云见日(下)
sql server 锁与事务拨云见日(中)的更多相关文章
- sql server 锁与事务拨云见日(上)
一.概述 讲到sql server锁管理时,感觉它是一个大话题,因为它不但重要而且涉及的知识点很多,重点在于要掌握高并发要先要掌握锁与事务,涉及的知识点多它包括各式各样的锁,锁的组合,锁的排斥,锁延伸 ...
- sql server 锁与事务拨云见日(下)
在锁与事务系列里已经写完了上篇中篇,这次写完下篇.这个系列俺自认为是有条不紊的进行,但感觉锁与事务还是有多很细节没有讲到,温故而知新可以为师矣,也算是一次自我提高总结吧,也谢谢大伙的支持.在上一篇的末 ...
- 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结
为什么说JAVA中要慎重使用继承 这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...
- [转]了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密_Mr_Indigo的空间
了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密 关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修 ...
- [翻译]:SQL死锁-锁与事务级别
其实这一篇呢与解决我项目中遇到的问题也是必不可少的.上一篇讲到了各种锁之间的兼容性,里面有一项就是共享锁会引起死锁,如何避免呢,将我们的查询都设置中read uncommitted是否可行呢?其结果显 ...
- 了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密
关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修改并释放锁,否则其他用户就无法修改该组数据. 有些数据库,包括SQL Se ...
- SQL Server锁类型
SQL Server锁类型(SQL)收藏 1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁. 2. NOLOCK:不添加共享锁和排它锁,当这个选项生 ...
- 转:sql server锁知识及锁应用
sql server锁(lock)知识及锁应用 提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题. 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用 ...
- SQL SERVER锁(LOCK)知识及锁应用
提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题. 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用户同时对数据库的并发操作时会带来以下数据不一致的 ...
随机推荐
- 《Java核心技术卷1》拾遗
之前对Java的基础知识有过学习,现在开始学习<Java核心技术卷1>,将一些新学的知识点,做简要记录,以备后续回顾: 1.double (1)所有的“非数值”都认为是不相同的 if(x= ...
- 使用Mobile Device Manager Plus mdm软件进行完备的移动设备管理
使用Mobile Device Manager Plus mdm软件进行完备的移动设备管理 什么是移动设备管理(mdm管理系统)? 移动设备管理(mdm管理系统)旨在管理企业内移动设备.管理员使用md ...
- Flink 报错 "Could not find a suitable table factory for 'org.apache.flink.table.factories.StreamTableSourceFactory' in the classpath"
先上代码: table = tablexx.select('*).tablexx.groupBy('x).select('x, xx.count ) tableEnvironment // decla ...
- (PMP)第4章-----项目整合管理
4.1 制定项目章程 输入 工具与技术 输出 1.商业文件 (商业论证,效益管理计划) 1.专家判断 1.项目章程 2.协议 2.数据收集 (头脑风暴,焦点小组,访谈) 2.假设日志 3.事业环境因素 ...
- 学以致用三十六-----弄懂python装饰器
看了海峰老师讲解的装饰器视频,讲解的非常棒.根据视频,记录笔记如下: 装饰器: 1.本质是函数,用def来定义.功能就是用来(装饰)其他函数,为其他函数添加附加功能 现有两个函数如下, def tes ...
- PowerShell工作流学习-5-自定义活动
关键点: a)除了内置活动和自定义活动,还可以用C# 编写自定义活动,并将其包括在 XAML 工作流和脚本工作流中,若要将自定义活动添加到脚本工作流中,请使用 #Requires 语句的 Assemb ...
- DelphiXE10.2.3——跨平台生成验证码图片
$("#img-code").bind( 'click', function () { $(this).attr('src','VerifyCode?t='+Math.random ...
- 2018年3月24日上海MVP线下技术交流活动简报
2018年3月24日下午,几位上海MVP自发组织了一次线下的技术交流会,主要由MVP胡浩牵头,我(陈晴阳).刘鑫.朱兴亮和胡浩各自做了一次主题演讲,具体主题是: 陈晴阳:<这还是我认识的Visu ...
- 电脑知识,一键开启Win10“超级性能模式”
现在主流系统以及从WIN7慢慢的转移到了WIN10,微软也为WIN10做了很多优化跟更新.今天要跟大家说的这个功能很多人肯定没有听说过.那就是WIN10的超级性能模式. 1. 大多数Win10是没有滴 ...
- Java 利用枚举封装接口返回 JSON 结构
利用枚举封装返回码和返回信息 package com.template.project.util; public enum StatusCode { SUCCESS(20000, "成功&q ...