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(未提交 读)

  顾名思义就是读出了还没有提交的数据,特点:效率高,但是就是容易出现脏读。最低的事物隔离级别,仅保证不读取物理受损的数据。

--开始事物
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(提交 读)

  顾名思义就是提交的数据才能读出来。

--开始事物
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语句读出的内容相同。

--设置锁级别
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   可串行读

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

时间: 2024-10-13 12:18:04

SQL-锁-事物级别的相关文章

SQL锁表解决并发性

在数据库开发过程中,不得不考虑并发性的问题,因为很有可能当别人正在更新表中记录时,你又从该表中读数据,那你读出来的数据有可能就不是你希望得到的数据.可以说有些数据同时只能有一个事物去更新,否则最终显示给用户的数据不是数据库中现存的数据.锁表就限制不同的事物在同一时间内不允许同时操作一张表,实例很简单,可以用select来锁定整张表,那别人就不可能更新或是读取表的记录.select * from dbo.Employee with(holdlock); with关键字来设置锁表的方式.下面是wit

SQL 锁的介绍

锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 丢失更新A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 脏读A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致 不可重复读A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致 并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做

sql锁 事务

1.数据库并发产生的问题.(这里所说的事务就是普通意义的流程,跟数据库的事务不要关联起来) 1)脏读.一个事读取了一个仍然在另一个未提交事务的范畴内的数据.read committed级别可以避免. 2)不可重复读.一个事务中两次相同的查询却返回了不同的数据.这是因为一个事务在读,然后另一个事务修改了数据,这个事务再去读,发现两次数据不一致. 3)幻读.没有锁定所有读取的行. 4)丢失更新. 2.各种锁(解决这些问题). 1)共享锁.用户在读取的时候其他用户可以读取,但是不能修改.select

SQL Server事物的存储过程

在酒店管理系统开发中,我们会创建房间表和房间类型表(房型表)这两个表,如下图所示: 房型表:RoomType 房间表:Room 首先这两个表的关系:Room是从表,RoomType是主表,两表有主外键关系,RoomType.rTypeId=Room.rTypeId 分析这两个表,我们会发现这样一个问题:在房间表和房型表管理中,当我们修改或者删除一个RoomType表,对应的Room表我们也要做修改和删除,那么我们怎么解决这个问题呢?首先可以在数据库中设置级联删除,或者利用触发器也可以解决...这

[翻译]——集群索引:通往SQL Server索引级别3的阶梯

集群索引:通往SQL Server索引级别3的阶梯 By David Durant 本文是楼梯系列的一部分:SQL Server索引的阶梯 索引是数据库设计的基础,并告诉开发人员使用数据库非常了解设计器的意图.不幸的是,当性能问题出现时,索引常常被添加到事后.这里最后是一个简单的系列文章,它应该能让任何数据库专业人员快速"跟上"他们的步伐 这个阶梯的前面的级别提供了一般的索引和非聚集索引的概述.它总结了关于SQL Server索引的关键概念.当请求到达数据库时,无论是SELECT语句还

SQL锁机制和事务隔离级别

摘自:http://www.cnblogs.com/haiyang1985/archive/2009/02/27/1399641.html 锁机制 NOLOCK和READPAST的区别. 1.       开启一个事务执行插入数据的操作. BEGIN TRAN t INSERT INTO Customer SELECT 'a','a' 2.       执行一条查询语句. SELECT * FROM Customer WITH (NOLOCK) 结果中显示"a"和"a&quo

转自高手关于SQL 锁的叙述。。(nolock,rowlock,tablock,xlock,paglock)

锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: [丢失更新]A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 [脏读]A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致 [不可重复读]A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致 并发控制的主要方法是封锁,锁就是在一段时间

30分钟全面解析-SQL事务+隔离级别+阻塞+死锁

以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式-上篇 [T-SQL基础]04.表表达式-下篇 [T-SQL基础]05.集合运算 [T-SQL基础]06.透视.逆透视.分组集 [T-SQL基础]07.数据修改 [T-SQL基础]08.事务和并发 [

SQL锁行 解决多台服务器发送统一请求并发问题

锁行信息SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 存储过程:SET Transaction Isolation Level Read语法的四种情况 这几天一直在弄存储过程,现在在这里跟大伙共享下资料: SET Transaction Isolation Level Read UNCOMMITTED 使用这句东东呢可以分为四种情况,现在就在这里逐一介绍: 第一种情况: READ   COMMITTED 这句的作用是: 指定在读取数据时控制共享

SQL事务隔离级别

数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了.这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来. 脏读(Dirty Reads) 一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交.这是相当危险的,因为很可能所有的操作都被回滚. 不可重复读(Non-repeatable Reads) 一个事