当前位置:Gxlcms > 数据库问题 > 数据库-锁的实践

数据库-锁的实践

时间:2021-07-01 10:21:17 帮助过:16人阅读

SELECT * FROM AppLog WITH (HOLDLOCK) /*共享锁*/

SELECT * FROM AppLog WITH (UPDLOCK)  /*更新锁*/ 

SELECT * FROM AppLog WITH (XLOCK) WHERE LogID=‘AA599A4E-B727-4A65-8010-00001661765E‘; /*排它锁*/  

SELECT * FROM AppLog WITH (ROWLOCK) WHERE LogID=‘6BE2C680-0C9F-43FA-9B4E-00000A6C1CEF‘; /*行锁*/ 

SELECT * FROM AppLog WITH (TABLOCKX) /*大容量更新锁*/ 

SELECT * FROM AppLog WITH (XLOCK,ROWLOCK) WHERE LogID=‘AA599A4E-B727-4A65-8010-00001661765E‘; /*锁的组合使用*/ 

/*XLOCK 本身是锁住数据行的,TABLOCKX是锁住整张表*/

SELECT * FROM AppLog WITH (NOLOCK)   /*不加锁,当一个事务回滚后,出现脏数据*/   

SELECT * FROM AppLog WITH (READPAST)  /*忽略掉加锁的数据(行数据,页数据)*/
技术分享

四:死锁的发生

比如现在的数据库用两个用户在用,

用户1:

BEGIN TRAN
SELECT * FROM AppLog WHERE LogID  = ‘A10BA165-6E52-4AFB-9EA8-000000D6B90A‘;
UPDATE AppLog SET AppPostion = AppPostion + AppPostion WHERE LogID = ‘A10BA165-6E52-4AFB-9EA8-000000D6B90A‘;

用户2:

BEGIN TRAN
SELECT * FROM AppLog WHERE LogID  = ‘A10BA165-6E52-4AFB-9EA8-000000D6B90A‘;
UPDATE AppLog SET AppPostion = AppPostion + AppPostion WHERE LogID = ‘A10BA165-6E52-4AFB-9EA8-000000D6B90A‘;


比如用户1,用户2同时执行 SELECT,用户1对记录加了共享锁,用户2对记录也加了共享锁,当用户1 SELECT 执行完毕,准备执行UPDATE的时候,根据锁机制,用户1的共享锁需要升
级到排他锁才能执行接下来的UPDATE.

在升级排他锁前,必须等待记录上的其它共享锁释放,但是因为共享锁只有等事务结束后才释放。因为用户2的共享锁不释放而导致用户1等(等用户2释放共享锁,自己好升级成排他锁),同理,这时也因为用户1的共享锁不释放而导致用户2等待。死锁就发生了。

五:无锁查询技巧

打开两个查询窗口:其中一个执行下面语句:

技术分享
CREATE TABLE a
(
    id INT ,
    name NVARCHAR(20)
) 
BEGIN TRAN
INSERT a VALUES (‘1‘,‘a‘)--开启一个事务,而不提交也不回滚,此时insert 语句产生的排它锁是不会释放的
技术分享

在另一个窗口中执行:

select COUNT(*) from a with(nolock)--无锁查询,会查出结果为1

select COUNT(*) from a with(readpast)--忽略所有有锁的记录,此时为0

然后执行select * from a --此时是查不出结果的,会无限地等待下去,因为排它锁未释放,默认查询的共享锁与之不兼容,所以就一直等待排它锁的释放,才会返回结果,即使表中已有许多数据,而排它锁只锁了一条记录,但是,查询语句也要等待这一条记录的锁的释放,才会返回结果。 这便是人工手动设置的因为排它锁未释放而导致的死锁(不是相互等待,而是一方无尽的等待!)。

 

欢迎讨论。

数据库-锁的实践

标签:数据   这一   sql   lock   strong   ref   环境   char   分类   

人气教程排行