SQL Server 锁 LOCK

本文详细介绍了SQL中的多种锁机制,包括NOLOCK、HOLDLOCK、ROWLOCK、UPDLOCK等,并通过实例展示了如何使用这些锁机制来实现并发控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库引擎存储过程
SET TRANSACTION ISOLATION LEVEL

在多用户的情况下不免要进行并发控制。微软提供了锁机制。
这里锁分为两个部分,一个是锁的范围(行锁、页面锁、表锁),另一个是锁的粒度(共享锁、持有锁等)
服务器带宽,服务器费用,开发人员费用,运维费用

NOLOCK、ROWLOCK、UPDLOCK

1、NOLOCK 不加锁
可以查询到记录 (不管是否被锁住,都查询出数据)所以可能会发生读出脏数据的情况,把没有提交事务的数据也显示出来。

select * from test with(nolock)

*
2、HOLDLOCK 保持锁

begin tran
select * from test with(holdlock) where id = 1 
rollback

*
3、ROWLOCK 行锁
使用 select * from dbo.A with(RowLock) WHRE a=1 这样的语句,系统是什么时候释放行锁呢??
RowLock 在不使用组合的情况下是没有任何意义的,With(RowLock,UpdLock) 这样的组合才成立,查询出来的数据使用 RowLock 来锁定,当数据被Update的时候,或者回滚之后,锁将被释放。
*
4、UPDLOCK 更新锁,修改锁
优点: 允许读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。

begin tran
select * from  WebManageUsers with (updlock) where LoginName = 'zzl'
waitfor delay '00:00:10'
update WebManageUsers set RealName = 'zzlreal11' where LoginName = 'zzl'
commit tran
go

begin tran
select * from SYS_DICT with (updlock) where FULLNAME = 'Z'
waitfor delay '00:00:10'
update SYS_DICT set FULLNAME = 'ZZ'
commit tran
go

begin transaction --开始一个事务
select Qty from myTable with (updlock) where Id in (1,2,3)
update myTable SET Qty = Qty - A.Qty from myTable  as A inner join  @_Table as B on A.ID = B.ID
commit transaction --提交事务
go

--案例
create procedure [dbo].[proc_sequence_select]
	@count int,
	@code varchar(20)
AS 
begin
	set nocount on
	begin try
	begin tran

		if @count > 0 and @code is not null
		begin
			declare @sequence_value bigint
			declare @start_value bigint
			
			select @sequence_value = sequence_value from sys_sequence with (updlock) where sequence_code = @code
			set @start_value = @sequence_value + 1
			set @sequence_value = @sequence_value + @count
			update sys_sequence set sequence_code=@sequence_value where sequence_code = @code

			select @start_value start_value,@sequence_value stop_value
		end
		else
		begin
			raiserror ( '错误!', 16, 1)
		end
		commit tran
	end try
	begin catch
		rollback tran
		--错误消息
		declare @msg nvarchar(max);
		set @msg = error_message();
		--insert into sys_error_message values( '错误类型',@msg, '错误数据', getdate());
		raiserror ( @msg, 16, 1);
	end catch;
end

5、READPAST
被锁住的记录不能查询出来。

select * from test ip with(readpast)

select * from test with(readpast)

*
6、TABLOCK 表锁
*
*
7、PAGLOCK 页锁
*
*
8、TABLOCKX 排它表锁
排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能“读取”或“修改”排它 (X) 锁锁定的数据。 
*
*
*
*
*
9、对应用程序资源设置锁
sp_getapplock

--锁定应用程序资源 
begin tran;  
declare @result int;  
exec @result = sp_getapplock @Resource = 'Form1',@LockMode = 'Shared';  
commit tran; 

*
10、为应用程序资源释放锁
sp_releaseapplock

--为应用程序资源解锁 
exec sp_releaseapplock @DbPrincipal = 'dbo', @Resource = 'Form1'; 

*
11、锁一个表的某一行

--可选参数【committed】【uncommitted】【read】【serializable】
set transaction isolation level read uncommitted
select * from test rowlock where id = 1 

*
12、查询锁

select
request_session_id spid
,OBJECT_NAME(resource_associated_entity_id) tableName
from sys.dm_tran_locks where resource_type='OBJECT'

*
13、解锁

declare @spid int
set @spid = 57 --锁表进程 
declare @sql varchar(1000)
set @sql='kill '+cast(@spid as varchar) 
exec(@sql)

*
*
*
*
*
*

SQL Server机制是数据库管理系统中用于控制并发访问和保证数据一致性的核心功能之一。通过机制,SQL Server 能够防止多个用户同时修改相同的数据,从而避免数据不一致、脏读、不可重复读等问题。 ### 的类型 SQL Server 支持多种类型的,以适应不同的并发需求和事务隔离级别: - **共享(Shared Lock, S)**:允许事务读取数据行。在共享存在时,其他事务可以获取共享,但不能获取排他。共享通常在 `SELECT` 语句执行时使用。 - **排他(Exclusive Lock, X)**:确保事务可以独占访问数据。在排他存在时,其他事务既不能获取共享也不能获取排他。排他通常在 `INSERT`, `UPDATE`, 或 `DELETE` 语句执行时使用。 - **更新(Update Lock, U)**:一种介于共享和排他之间的。当 SQL Server 准备更新数据时,会先获取更新,之后再升级为排他。更新可以防止死的发生。 - **意向(Intent Locks)**:表示某个事务希望在更低层级的资源上获取。例如,表级意向表示事务可能在该表的某些行上加。 - **架构(Schema Locks)**:用于保护数据库对象的结构,如表或索引的定义。在对数据库对象进行更改时会使用架构。 - **大容量更新(Bulk Update Locks)**:用于支持大容量复制操作,可以在不影响其他事务的情况下进行大量数据加载[^2]。 ### 的粒度 SQL Server 支持不同级别的粒度,包括但不限于: - **行级(Row-Level Locking)**:定单个数据行,适用于高并发环境下的细粒度控制。 - **页级(Page-Level Locking)**:定包含多行数据的数据页。 - **表级(Table-Level Locking)**:定整个表,通常在大规模数据操作时使用。 ### 死与阻塞 当两个或更多事务互相等待对方释放资源上的时,就会发生死SQL Server 有一个死检测机制,能够自动识别并解决死问题,通常是通过回滚其中一个事务来打破循环依赖。阻塞则发生在某个事务必须等待另一个事务释放其所需的时。长时间的阻塞会影响系统性能,因此需要合理设计应用程序逻辑和事务处理流程。 ### 使用指南 为了有效管理和优化 SQL Server 中的行为,以下是一些最佳实践建议: - **最小化事务持有时间**:尽量减少事务的持续时间,以便尽快释放持有的,降低阻塞的可能性。 - **保持一致性访问顺序**:确保所有事务按照相同的顺序访问资源,有助于减少死的发生。 - **选择合适的隔离级别**:根据业务需求选择适当的事务隔离级别。较低的隔离级别可能会导致更多的并发问题,而较高的隔离级别则可能导致更多的竞争。 - **监控活动**:利用 SQL Server 提供的动态管理视图 (DMVs) 和性能计数器来监视的状态和趋势,及时发现潜在的问题。 - **调整索引策略**:合理的索引设计可以帮助减少查询过程中需要扫描的数据量,进而减少定的范围和数量。 ```sql -- 示例:查看当前活动的信息 SELECT request_session_id AS SPID, OBJECT_NAME(resource_associated_entity_id) AS ObjectName, resource_type AS ResourceType, request_mode AS RequestMode, request_status AS RequestStatus FROM sys.dm_tran_locks WHERE resource_type != 'DATABASE'; ``` 以上代码片段展示了如何使用动态管理视图 `sys.dm_tran_locks` 来获取当前实例中所有非数据库级别的信息。这有助于 DBA 快速定位到具体的争用情况,并采取相应的措施进行调优。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值