返回顶部
首页 > 资讯 > 数据库 >sqlserver中的事务和锁的详细介绍
  • 815
分享到

sqlserver中的事务和锁的详细介绍

2024-04-02 19:04:59 815人浏览 独家记忆
摘要

本篇内容主要讲解“sqlserver中的事务和锁的详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“sqlserver中的事务和锁的详细介绍”吧!一、脏读、

本篇内容主要讲解“sqlserver中的事务的详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“sqlserver中的事务和锁的详细介绍”吧!

一、脏读、不可重复读、幻读

(1)脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

例如:

张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。

与此同时,

事务B正在读取张三的工资,读取到张三的工资为8000。

随后,

事务A发生异常,而回滚了事务。张三的工资又回滚为5000。

最后,

事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。

(2)不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

例如:

在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。

与此同时,

事务B把张三的工资改为8000,并提交了事务。

随后,

在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。

(3)幻读: 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

例如:

目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。

此时,

事务B插入一条工资也为5000的记录。

这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。

不可重复读的重点是修改: 同样的条件,你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增或者删除:同样的条件,第 1 次和第 2 次读出来的记录数不一样

二、独占锁、共享锁、更新锁,乐观锁、悲观锁

1、锁的两种分类方式

(1)从数据库系统的角度来看,锁分为以下三种类型:

•独占锁(Exclusive Lock)独占锁锁定的资源只允许进行锁定操作的程序使用,其它任何对它的操作均不会被接受。执行数据更新命令,即INSERT、 UPDATE 或DELETE 命令时,SQL Server 会自动使用独占锁。但当对象上有其它锁存在时,无法对其加独占锁。独占锁一直到事务结束才能被释放。

•共享锁(Shared Lock)共享锁锁定的资源可以被其它用户读取,但其它用户不能修改它。在SELECT 命令执行时,SQL Server 通常会对对象进行共享锁锁定。通常加共享锁的数据页被读取完毕后,共享锁就会立即被释放。

•更新锁(Update Lock)更新锁是为了防止死锁而设立的。当SQL Server 准备更新数据时,它首先对数据对象作更新锁锁定,这样数据将不能被修改,但可以读取。等到SQL Server 确定要进行更新数据操作时,它会自动将更新锁换为独占锁。但当对象上有其它锁存在时,无法对其作更新锁锁定。

(2)从程序员的角度看,锁分为以下两种类型:

•悲观锁(Pessimistic Lock)悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。 

•乐观锁(Optimistic Lock)相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。

而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

2、数据库中如何使用锁

首先从悲观锁开始说。在SqlServer等其余很多数据库中,数据的锁定通常采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插入机制,在任何时间同一张表只会插1条数据,别的想插入的数据要等到这一条数据插完以后才能依次插入。带来的后果就是性能的降低,在多用户并发访问的时候,当对一张表进行频繁操作时,会发现响应效率很低,数据库经常处于一种假死状态。而oracle用的是行级锁,只是对想锁定的数据才进行锁定,其余的数据不相干,所以在对Oracle表中并发插数据的时候,基本上不会有任何影响。

注:对于悲观锁是针对并发的可能性比较大,而一般在我们的应用中用乐观锁足以。

Oracle的悲观锁需要利用一条现有的连接,分成两种方式,从SQL语句的区别来看,就是一种是for update,一种是for update nowait的形式。比如我们看一个例子。

首先建立测试用的数据库表:

CREATE TABLE TEST(ID,NAME,LOCATION,VALUE,CONSTRAINT test_pk PRIMARY KEY(ID))AS SELECT deptno, dname, loc, 1 FROM scott.dept

这里我们利用了Oracle的Sample的scott用户的表,把数据copy到我们的test表中。

(1)for update 形式介绍

然后我们看一下for update锁定方式。我们执行如下的select for update语句:

select * from test where id = 10 for update

通过这条检索语句锁定以后,再开另外一个sql*plus窗口进行操作,再把上面这条sql语句执行一便,你会发现sqlplus好像死在那里了,好像检索不到数据的样子,但是也不返回任何结果,就属于卡在那里的感觉。这个时候是什么原因呢,就是一开始的第一个Session中的select for update语句把数据锁定住了。由于这里锁定的机制是wait的状态(只要不表示nowait那就是wait),所以第二个Session(也就是卡住的那个sql*plus)中当前这个检索就处于等待状态。当第一个session最后commit或者rollback之后,第二个session中的检索结果就是自动跳出来,并且也把数据锁定住。

不过如果你第二个session中你的检索语句如下所示:select * from test where id = 10,也就是没有for update这种锁定数据的语句的话,就不会造成阻塞了。

(2)for update nowait 形式介绍

另外一种情况,就是当数据库数据被锁定的时候,也就是执行刚才for update那条sql以后,我们在另外一个session中执行for update nowait后又是什么样呢。

比如如下的sql语句:

select * from test where id = 10 for update nowait

由于这条语句中是制定采用nowait方式来进行检索,所以当发现数据被别的session锁定中的时候,就会迅速返回ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源。所以在程序中我们可以采用nowait方式迅速判断当前数据是否被锁定中,如果锁定中的话,就要采取相应的业务措施进行处理。

那这里另外一个问题,就是当我们锁定住数据的时候,我们对数据进行更新和删除的话会是什么样呢。

比如同样,我们让第一个Session锁定住id=10的那条数据,我们在第二个session中执行如下语句:

update test set value=2 where id = 10

这个时候我们发现update语句就好像select for update语句一样也停住卡在这里,当你第一个session放开锁定以后update才能正常运行。当你update运行后,数据又被你update 语句锁定住了,这个时候只要你update后还没有commit,别的session照样不能对数据进行锁定更新等等。

总之,Oracle中的悲观锁就是利用Oracle的Connection对数据进行锁定。在Oracle中,用这种行级锁带来的性能损失是很小的,只是要注意程序逻辑,不要给你一不小心搞成死锁了就好。而且由于数据的及时锁定,在数据提交时候就不呼出现冲突,可以省去很多恼人的数据冲突处理。缺点就是你必须要始终有一条数据库连接,就是说在整个锁定到最后放开锁的过程中,你的数据库联接要始终保持住。

与悲观锁相对的,我们有了乐观锁。乐观锁一开始也说了,就是一开始假设不会造成数据冲突,在最后提交的时候再进行数据冲突检测。

在乐观锁中,我们有3种常用的做法来实现:

•第一种就是在数据取得的时候把整个数据都copy到应用中,在进行提交的时候比对当前数据库中的数据和开始的时候更新前取得的数据。

当发现两个数据一模一样以后,就表示没有冲突可以提交,否则则是并发冲突,需要去用业务逻辑进行解决。

•第二种乐观锁的做法就是采用版本戳,这个在Hibernate中得到了使用。

采用版本戳的话,首先需要在你有乐观锁的数据库table上建立一个新的column,比如为number型,当你数据每更新一次的时候,版本数就会往上增加1。

比如同样有2个session同样对某条数据进行操作。两者都取到当前的数据的版本号为1,当第一个session进行数据更新后,在提交的时候查看到当前数据的版本还为1,和自己一开始取到的版本相同。就正式提交,然后把版本号增加1,这个时候当前数据的版本为2。当第二个session也更新了数据提交的时候,发现数据库中版本为2,和一开始这个session取到的版本号不一致,就知道别人更新过此条数据,这个时候再进行业务处理,比如整个Transaction都Rollback等等操作。

在用版本戳的时候,可以在应用程序侧使用版本戳的验证,也可以在数据库侧采用Trigger(触发器)来进行验证。不过数据库的Trigger的性能开销还是比较的大,所以能在应用侧进行验证的话还是推荐不用 Trigger。

•第三种做法和第二种做法有点类似,就是也新增一个Table的Column,不过这次这个column是采用timestamp型,存储数据最后更新的时间。

在Oracle9i以后可以采用新的数据类型,也就是timestamp with time zone类型来做时间戳。这种Timestamp的数据精度在Oracle的时间类型中是最高的,精确到微秒(还没与到纳秒的级别),一般来说,加上数据库处理时间和人的思考动作时间,微秒级别是非常非常够了,其实只要精确到毫秒甚至秒都应该没有什么问题。

和刚才的版本戳类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。如果不想把代码写在程序中或者由于别的原因无法把代码写在现有的程序中,也可以把这个时间戳乐观锁逻辑写在Trigger或者存储过程中。

三、事务五种隔离级别

Isolation 属性一共支持五种事务设置,具体介绍如下:

(1)DEFAULT

使用数据库设置的隔离级别(默认),由DBA 默认的设置来决定隔离级别。

(2)READ_UNCOMMITTED

这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。

会出现脏读、不可重复读、幻读 (隔离级别最低,并发性能高)。

(3)READ_COMMITTED

保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。

可以避免脏读,但会出现不可重复读、幻读问题(锁定正在读取的行)。

(4)REPEATABLE_READ

可以防止脏读、不可重复读,但会出幻读(锁定所读取的所有行)。

(5)SERIALIZABLE

这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。

保证所有的情况不会发生(锁表)。

到此,相信大家对“sqlserver中的事务和锁的详细介绍”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: sqlserver中的事务和锁的详细介绍

本文链接: https://lsjlt.com/news/60356.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • sqlserver中的事务和锁的详细介绍
    本篇内容主要讲解“sqlserver中的事务和锁的详细介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“sqlserver中的事务和锁的详细介绍”吧!一、脏读、...
    99+
    2024-04-02
  • SQLServer中的事务介绍
    事务全部是关于原子性的。原子性的概念是指可以把一些事情当做一个单元来看待。从数据库的角度看,它是指应全部执行或全部都不执行的一条或多条语句的最小组合。为了理解事务的概念,需要能够定义...
    99+
    2024-04-02
  • Spring事务的详细介绍
    本篇内容介绍了“Spring事务的详细介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言Spring事务管理我相信大家都用得很多,但可能...
    99+
    2023-06-04
  • 详细介绍Java中的各种锁
    一、一张图了解21种锁 二、乐观锁 应用 CAS 思想 一种乐观思想,假定当前环境是读多写少,遇到并发写的概率比较低,读数据时认为别的线程不会正在进行修改 实现 写数据...
    99+
    2024-04-02
  • Java中的各种锁详细介绍
    这篇文章主要讲解了“Java中的各种锁详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中的各种锁详细介绍”吧!锁有什么作用呢说了这么多还是不清楚锁到底有什么用处这一点就要深思我...
    99+
    2023-06-16
  • mysql事务详细介绍
    目录简介事务四个特性事务隔离级别验证MVCC当前读快照读当前读、快照读、MVCC关系mvcc 解决的问题MVCC实现原理可见性规则简介 事务是由一组sql语句组成的逻辑处理单元 事务...
    99+
    2024-04-02
  • Go GORM 事务详细介绍
    目录禁用默认事务事务嵌套事务手动事务一个特殊的示例SavePoint、RollbackTo禁用默认事务 为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果...
    99+
    2024-04-02
  • Redis中GETBIT和SETBIT的详细介绍
    本篇内容介绍了“Redis中GETBIT和SETBIT的详细介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2024-04-02
  • c++中string和vector的详细介绍
    目录知识点1【STL的概述】知识点2【迭代器的案例】知识点3【string类】1、案例:string的构造和赋值知识点1【STL的概述】 STL(Standard Template ...
    99+
    2024-04-02
  • 【MySQL进阶教程】锁的详细介绍
    前言 本文为 【MySQL进阶教程】锁 相关知识,下边将对锁的概述,全局锁(包含全局锁的介绍,语法与特点),表级锁(包含表级锁的介绍,表锁,元数据锁,意向锁),行级锁(包含行级锁的介绍,行锁,间隙锁...
    99+
    2023-09-01
    mysql 数据库 java
  • H5的事件属性详细介绍
    这篇文章主要介绍“H5的事件属性详细介绍”,在日常操作中,相信很多人在H5的事件属性详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”H5的事件属性详细介绍”的疑惑有所帮...
    99+
    2024-04-02
  • MySQL事务和InnoDB锁类型介绍
    这篇文章为大家带来有关MySQL事务和InnoDB锁类型的介绍。文章涵盖MySQL事务和InnoDB锁类型的知识点,希望大家通过这篇文章能有所收获。一、事务的隔离级别1、4 种隔离级别(1)未提交读(Rea...
    99+
    2024-04-02
  • Java中死锁和释放锁的基本介绍和细节讨论
    死锁(Deadlock)是多线程编程中的一个经典问题,指的是两个或多个线程互相等待对方释放资源,从而导致程序无法继续执行的状态。 死锁产生的条件,通常被称为死锁的“必要条件”,包括: 互斥条件(Mutual Exclusion): 一个资...
    99+
    2023-08-30
    java jvm 开发语言
  • Android中的WebView详细介绍
    Android中WebView的详细解释: 1. 概念: WebView(网络视图)能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页。 2. ...
    99+
    2022-06-06
    webview Android
  • jQuery中Ajax的详细介绍
    这篇文章主要介绍“jQuery中Ajax的详细介绍”,在日常操作中,相信很多人在jQuery中Ajax的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jQuery中A...
    99+
    2024-04-02
  • Java中CompletableFuture 的详细介绍
    目录1.概述1.0 创建 CompletableFuture 的对象的工厂方法1.1 non-async 和 async 区别1.1.1 non-async 示例:注册 action...
    99+
    2024-04-02
  • Python中栈的详细介绍
    目录1、问题描述2、解决方案3、结语本文转自公众号:"算法与编程之美" 1、问题描述 Python中数据类型有列表,元组,字典,队列,栈,树等等。像列表,元组这样的都是python内...
    99+
    2024-04-02
  • Linux中的LVM的详细介绍
    这篇文章主要介绍“Linux中的LVM的详细介绍”,在日常操作中,相信很多人在Linux中的LVM的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux中的LVM的详细介绍”的疑惑有所帮助!接下来...
    99+
    2023-06-13
  • 【MySQL基础教程】事务详细介绍
    前言 本文为 【MySQL基础教程】事务 相关知识,下边将对事务简介,事务操作(包括:未控制事务,控制事务),事务四大特性,并发事务问题,事务隔离级别等进行详尽介绍~ 📌博主主页:小...
    99+
    2023-09-04
    mysql java 数据库
  • Flink的详细介绍
    这篇文章主要介绍“Flink的详细介绍”,在日常操作中,相信很多人在Flink的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Flink的详细介绍”的疑惑有所帮助!接...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作