SQL SERVER中,多个事物间同是并发操作数据时,会发生事务之间数据读取不一致的 情况,

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL SERVER中,多个事物间同是并发操作数据时,会发生事务之间数据读取不一致的 情况,相关的知识,希望对你有一定的参考价值。

因此并发的多个事务间是相互分开的,一个事务内部操作的数据不能被另一个事务
进行修改,这主要体现了事务的( c)特性。

a) 一致性 b) 持久性 c) 原子性 d) 隔离性
3)运行以下语句,输出结果是( c )。
CREATE PROC proc_lookup
@mystuNo varchar(8)=NULL
AS
If @mystuNo IS NULL
BEGIN
Print ‘您忘记了传递学员参数’
Return
End
SELECT * FROM stuinfo where stuNo = @mystuNO
Go
EXEC proc_lookup
a)编设错误 b)调用存储 proc_lookup 过程出错
c)显示“您忘记了传递学员参数” d)显示空的学员信息记录集
帮忙做做

第一题,你自己去看看acid特性就理解了,
第二题我。因为循环体里面是@mystuno为空值是才打印那几个字,而你在创建存储过程的时候定义了这个变量为空,现在你的查询语句条件就是这个参数变量,所以就执行循环语句,所以就是选c了
参考技术A 第一个选A 第二题选B 第一题我就不多说了,多看课本上面的讲解。第二题的代码前面存储过程的创建是对的,但是执行就必须有参数,没参数就不能执行。不执行自然就不能调用前面的存储过程,虽然前面的存储过程逻辑上定义没参数就显示信息,但是不执行存储过程,就什么都显示不了。本回答被提问者采纳

SQL-锁-事物级别

一、锁

  锁是一种安全机制,控制并发操作,防止用户读取其他用户正在更改的数据,或者多用户同时修改一个数据,从而保证事物的完整性和数据库的一致性。SQLserver 会自动强制执行锁,但是用户可以通过对锁进行了解并在应用程序中自定义锁来设计出高效率的应用程序。锁确定了并发事物访问资源的方式。

二、锁分类

共享锁:

  共享锁,锁定的资源可以被其他用户读取,但是其他用户不能听修改他(只读操作),  例如在select语句执行时,sqlserver 会对 对象进行共享锁锁定,对加共享锁的资源读取完毕之后,共享锁立即释放。(对于事物级别中 repeattable read,是这样的,在一个事物中,select 语句获取共享锁,查询完之后,不会释放共享锁,只有等到事物结束才会释放共享锁。)

排他锁:

  排它锁只允许锁定他的程序操作他。其他任何操作都不会被接受。例如执行update insert delete时sqlserver会自动是用排他锁,确保不会同时对一个资源多种操作。当对象上有其他锁时,无法对资源添加排它锁(这个也是事物中read commited 原理)。排它锁一直到事物结束才释放。

更新锁:

  用户更新资源时,防止死锁。

   下面是死锁现象

                              

  上面两个相同的事物同时执行,同时获取共享锁,  当他们更新的时候需要获取排它锁,但是由于其他事物存在其他类型的锁,不能使用排它锁,导致锁等待,都在等待另外一个事物释放共享锁。导致锁死。

  更新锁,可以防止死锁问题。因为一次只能有一个事物获取资源的更新锁,其他事物只能获得共享锁。sqlserver准备更新数据时,首先对资源添加更新锁,这样其他事物不能修改,只能读取。等到sqlserver确定要更新资源时,自动将更新锁转换为排它锁,否则锁转化为共享锁。

三、事物级别
CREATE DATABASE Test
GO
USE [Test]
GO
/****** Object:  Table [dbo].[UserTable]    Script Date: 2017/7/20 14:00:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserTable](
    [UserID] [int] IDENTITY(1,1) NOT NULL,
    [UserName] [nvarchar](50) NULL,
    [NewClo] [int] NULL,
 CONSTRAINT [PK_UserTable] PRIMARY KEY CLUSTERED 
(
    [UserID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
数据库初始化脚本

  四种常用级别,由低到高。设置事物级别   SET TRANSACTION ISOLATION LEVEL  +  事物级别。默认事物级别为READ COMMIT

READ UNCOMMITED(未提交 读)

   顾名思义就是读出了还没有提交的数据,特点:效率高,但是就是容易出现脏读。最低的事物隔离级别,仅保证不读取物理受损的数据。。事物中修改的行 udpate  delete inset  行,select的时候要不会获取该行的共享锁(UNCOMMITED),所有select不要等待。

--开始事物
BEGIN TRANSACTION
--查询第一次,获取共享锁,查询完之后马上释放共享锁
SELECT * FROM UserTable AS ut
--插入数据,获取 修改数据的 排它锁
insert INTO UserTable
(
    -- UserID -- this column value is auto-generated
    UserName,
    NewClo
)VALUES(\'西伯利亚的狼\',1)
--等到15秒,让其他用户查询
WAITFOR DELAY \'00:00:15\'
--第二次查询,会查到西伯利亚的狼
SELECT * FROM UserTable AS ut
--commit時候自动释放排他锁
COMMIT TRANSACTION
新增脚本:添加数据事物
--设置事物级别
SET TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED
SELECT * FROM UserTable AS ut WHERE ut.UserName=\'西伯利亚的狼\'
查询脚本:设置事物级别并查询上面添加进去的数据
--即使上面有拍它所,也可以查出来
SELECT * FROM UserTable AS ut WITH (NOLOCK)  WHERE ut.UserName=\'西伯利亚的狼\'
设置锁查询:表明 as 别名 with(nolock),使锁定的数据也能读出来。

  先执行新增脚本,在马上执行查询脚本,由于新增脚本要等待15秒,事物未提交,但是查询脚本还是把未提交事物的数据查询出来了,设置锁查询with (nolock)也可以查询出来。称为脏读。(但是这种读取的效率高,不等待其他锁,就是会出现脏读。很多和钱打交道的行业比较敏感)

READ COMMIT(提交 读)

   顾名思义就是提交的数据才能读出来。事物中修改的行 udpate  delete inset  行,select的时候要获取该行的共享锁,但是排它锁已经占有,所有select要等待。

--开始事物
BEGIN TRANSACTION
--查询第一次,获取共享锁,查询完之后马上释放共享锁
SELECT * FROM UserTable AS ut
--插入数据,获取 修改数据的 排它锁
insert INTO UserTable
(
    -- UserID -- this column value is auto-generated
    UserName,
    NewClo
)VALUES(\'西伯利亚的狼\',1)
--等到15秒,让其他用户查询
WAITFOR DELAY \'00:00:15\'
--第二次查询,会查到西伯利亚的狼
SELECT * FROM UserTable AS ut
--commit時候自动释放排他锁
COMMIT TRANSACTION
新增脚本:添加数据事物
--设置事物级别
SET TRANSACTION ISOLATION LEVEL
READ COMMITTED
SELECT * FROM UserTable AS ut WHERE ut.UserName=\'西伯利亚的狼\'
查询脚本:设置事物级别并查询上面添加进去的数据

  先执行新增脚本,在马上执行查询脚本,由于新增脚本要等待15秒,事物未提交,查询脚本不能把新加的数据读出来,只能等事物提交完毕,才能读来。默认事物级别

REPEATTABLE READ(重复 读)

    select语句读取出来的数据在整个语句执行过程中不会被更改。同一个事物中,两个相同的SQL语句独处内容不同,出现幻读。目的保持同一个事物中相同的SQL语句读出的内容相同。  update  delete  时候不会痴线幻读,insert出现幻读,      因为select时共享锁持续到事物结束,导致,update delete不能获取拍它锁,

--设置锁级别
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRANSACTION

SELECT * FROM Test AS t WHERE t.ID=1
--登台15秒  让其他用户修改这一条数据
WAITFOR DELAY \'00:00:15\'

SELECT * FROM Test AS t WHERE t.ID=1

COMMIT TRANSACTION
查询脚本:设置了重复读级别,查询的共享锁只有在事物结束时才被释放,导致其他修改操作不能获取排它锁。
UPDATE Test
SET
    -- ID -- this column value is auto-generated
    Name = NEWID() WHERE ID=1
修改脚本:修改正在被查询的数据,由于不能获取到排它锁,所以等待

  先执行查询脚本,在马上执行修改脚本,查询脚本等待15秒,共享锁没有释放,所以导致修改脚本也在等待。

 SERIALIZABLE   可串行读

最高的事物隔离级别,使事物之间完全隔离,串行执行。将共享锁保持到事物完成。事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

以上是关于SQL SERVER中,多个事物间同是并发操作数据时,会发生事务之间数据读取不一致的 情况,的主要内容,如果未能解决你的问题,请参考以下文章

postgresql 有悲观锁和乐观锁吗

事物再次深刻理解

SQL Server 事务与锁

锁与并发-SQL Server

Spring事物管理简介 (转)

SQL-锁-事物级别