我的编程空间,编程开发者的网络收藏夹
学习永远不晚

database如何实现锁不住的查询

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

database如何实现锁不住的查询

这篇文章主要介绍了如何实现锁不住的查询,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。

USE master;
GO
IF @@TRANCOUNT > 0
ROLLBACK TRAN;
GO
-- =======================================
-- 建立测试数据库
-- a. 删除测试库, 如果已经存在的话
IF DB_ID(N'db_xlock_test') IS NOT NULL
BEGIN;
ALTER DATABASE db_xlock_test
SET SINGLE_USER
WITH
ROLLBACK AFTER 0;
DROP DATABASE db_xlock_test;
END;
-- b. 建立测试数据库
CREATE DATABASE db_xlock_test;
-- c. 关闭READ_COMMITTED_SNAPSHOT 以保持SELECT 的默认加锁模式
ALTER DATABASE db_xlock_test
SET READ_COMMITTED_SNAPSHOT OFF;
GO
-- =======================================
-- 建立测试表
USE db_xlock_test;
GO
CREATE TABLE dbo.tb(
id int IDENTITY
PRIMARY KEY,
name sysname
);
INSERT dbo.tb
SELECT TOP(50000)
O1.name + N'.' + O2.name + N'.' + O3.name
FROM sys.objects O1 WITH(NOLOCK),
sys.objects O2 WITH(NOLOCK),
sys.objects O3 WITH(NOLOCK);
GO

然后,建立一个连接,执行下面的脚本来实现加锁。

-- =======================================
-- 测试连接1 - 加锁
BEGIN TRAN
--测试的初衷是通过SELECT加锁,结果发现UPDATE也锁不住
UPDATE dbo.tb SET name = name
--SELECT COUNT(*) FROM dbo.tb WITH(XLOCK)
WHERE id <= 2;
SELECT
spid = @@SPID,
tran_count = @@TRANCOUNT,
database_name = DB_NAME(),
object_id = OBJECT_ID(N'dbo.tb', N'Table');
-- 显示锁
EXEC sp_lock@@SPID;

通过执行结果,可以看到对象被加锁的情况:表级和页级上是IX锁,记录上是X锁。

spid

tran_count

database_name

object_id


51

1

db_xlock_test

21575115


spid

dbid

ObjId

IndId

Type

Resource

Mode

Status

51

7

0

0

DB


S

GRANT

51

7

21575115

1

PAG

0.095138889

IX

GRANT

51

7

21575115

0

TAB


IX

GRANT

51

1

1131151075

0

TAB


IS

GRANT

51

7

21575115

1

KEY

(020068e8b274)

X

GRANT

51

7

21575115

1

KEY

-10086470766

X

GRANT

然后新建一个连接,执行下面的T-SQL查询,看看会否被连接1锁住

-- =======================================
-- 测试连接2 - 被阻塞(在测试连接1 执行后执行)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM dbo.tb
WHERE id <= 2;

上述查询会很快返回结果,并不会被查询1阻塞住。

按照我们的了解(联机帮助上也有说明),在READ COMMITTED事务隔离级别下,查询使用共享锁(S),而根据锁的兼容级别,S锁是与X锁冲突的,所以正常情况下,连接2的查询需要等待连接1执行完成。可是测试的结果去违反了这一原则。

为了了解为什么连接2不会被阻塞,对连接2做了一个Trace,发现一个更郁闷的问题,Trace的结果如下:

EventClass

TextData

ObjectID

Type

Mode

Lock:Acquired

21575115

5 - OBJECT

6 - IS

Lock:Acquired

1:77

0

6 - PAGE

6 - IS

Lock:Acquired

[PLANGUIDE]

0

2 - DATABASE

3 - S

Lock:Acquired

21575115

5 - OBJECT

6 - IS

Lock:Acquired

1:77

0

6 - PAGE

6 - IS

Lock:Acquired

1:80

0

6 - PAGE

6 - IS

Lock:Acquired

1:89

0

6 - PAGE

6 - IS

Trace的前面两行是连接2的Trace结果,从结果看,连接2仅使用了意向共享锁(IS),而且只是表级和页级,按照锁的兼容性原则,IS和IX(连接1在表级和页级仅使用了IX锁)是不冲突的,所以连接2的查询不会被阻塞。在增加了查询的数据量后,Trace结果表明查还是只在表级和页级使用了IS锁(Trace结果的最后4行)。

对于这个问题,解决的办法当然就是提升连接1锁的粒度,使用PAGLOCK表提示将锁的粒度提升到页级,这样IS与X是冲突的,就可以成功阻塞连接2。

但疑问就是,为什么查询只在表级和页级下意向共享锁(IS),而不在行级下共享锁(X),这个似乎与联机帮助上的说明不一样(还是一直以来理解上的偏差呢)。

附:联机帮助上关于锁模式的说明

共享锁

共享锁(S 锁)允许并发事务在封闭式并发控制下读取 (SELECT) 资源。

更新锁

更新锁(U 锁)可以防止常见的死锁。在可重复读或可序列化事务中,此事务读取数据 [获取资源(页或行)的共享锁(S 锁)],然后修改数据 [此操作要求锁转换为排他锁(X 锁)]。如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为排他锁(X 锁)。共享模式到排他锁的转换必须等待一段时间,因为一个事务的排他锁与其他事务的共享模式锁不兼容;发生锁等待。第二个事务试图获取排他锁(X 锁)以进行更新。由于两个事务都要转换为排他锁(X 锁),并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。

若要避免这种潜在的死锁问题,请使用更新锁(U 锁)。一次只有一个事务可以获得资源的更新锁(U 锁)。如果事务修改资源,则更新锁(U 锁)转换为排他锁(X 锁)。

排他锁

排他锁(X 锁)可以防止并发事务对资源进行访问。使用排他锁(X 锁)时,任何其他事务都无法修改数据;仅在使用 NOLOCK 提示或未提交读隔离级别时才会进行读取操作。

数据修改语句(如 INSERT、UPDATE 和 DELETE)合并了修改和读取操作。语句在执行所需的修改操作之前首先执行读取操作以获取数据。因此,数据修改语句通常请求共享锁和排他锁。例如,UPDATE 语句可能根据与一个表的联接修改另一个表中的行。在此情况下,除了请求更新行上的排他锁之外,UPDATE 语句还将请求在联接表中读取的行上的共享锁。

意向锁

数据库引擎使用意向锁来保护共享锁(S 锁)或排他锁(X 锁)放置在锁层次结构的底层资源上。意向锁之所以命名为意向锁,是因为在较低级别锁前可获取它们,因此会通知意向将锁放置在较低级别上。

感谢你能够认真阅读完这篇文章,希望小编分享如何实现锁不住的查询内容对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,遇到问题就找亿速云,详细的解决方法等着你来学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

database如何实现锁不住的查询

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何实现在Linux下锁住键盘和鼠标而不锁屏

这期内容当中小编将会给大家带来有关如何实现在Linux下锁住键盘和鼠标而不锁屏,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。假如在你正看着屏幕上的某些重要的事情时,你不想让你的小猫或者小狗在你的键盘上行走
2023-06-06

mysql查询锁表的实现方法

目录1.查看表是否被锁2.查看表被锁状态和结束死锁步骤3.mysql查询锁表指令速查今天在做数据更新的时候,发现表中数据量不大,但是更新语句执行很久都没成功,经过查询后发现是表锁死导致的,本文记录一下锁表解决步骤:1.查看js表是否被锁
mysql查询锁表的实现方法
2024-09-04

如何实现OJB查询

这篇文章给大家分享的是有关如何实现OJB查询的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。OJB查询联接:在path expressions中(relationship.attribute)声明的联接在crite
2023-06-03

python如何实现查询

这篇文章主要为大家展示了“python如何实现查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何实现查询”这篇文章吧。查询排序和查询都是好基友,长的数据结构里面(字典,列表)里面
2023-06-16

如何实现JPQL的关联查询

小编给大家分享一下如何实现JPQL的关联查询,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!从一关联到多的查询和从多关联到一的查询来简单说说关联查询。实体Team:
2023-06-17

java如何实现跨库查询

在Java中,可以使用JDBC(Java Database Connectivity)来实现跨库查询。以下是一个简单的示例:```javaimport java.sql.*;public class CrossDatabaseQueryEx
2023-09-14

css如何实现容器查询

这篇文章主要为大家展示了“css如何实现容器查询”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“css如何实现容器查询”这篇文章吧。容器查询1. 基本概念容器查询使我们能够根据其父元素的大小设置元
2023-06-27

MySQL联合查询如何实现

这篇文章主要介绍“MySQL联合查询如何实现”,在日常操作中,相信很多人在MySQL联合查询如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL联合查询如何实现”的疑惑有所帮助!接下来,请跟着小编
2023-07-04

编程热搜

目录