曲苑杂坛--DML操作中如何处理那些未提交的数据

对数据库稍有了解的人,数据库使用排他锁X锁来避免两个事务同时修改同一条数据,同时使用较低级别如行上加锁来提高并发度。

以下了两种场景很容易理解:

1>事务1执行 UPDATE TB1 SET C2=1 WHERE C1=1(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=1,事务2必须等到事务1提交或回滚后,才能获得对该行数据的X锁;

2>事务1执行 UPDATE TB1 SET C2=1 WHERE C1=1(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=2,由于事务1和2修改的数据行不同,因此事务1和事务2不会阻塞;

但对于以下两种场景就有些难理解:

1>事务1执行 UPDATE TB1 SET C1=11 WHERE C1=1(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=11,数据行在事务1更新前不满足事务2的更新条件,但数据行在事务1更新后又满足事务2的更新条件,事务2会被事务1阻塞么?

测试结果:会被阻塞

测试代码:

DROP TABLE dbo.TB1
GO
CREATE TABLE TB1
(
    C1 INT,
    C2 INT
)
GO
CREATE UNIQUE CLUSTERED  INDEX IDX_C1
ON dbo.TB1
(
    C1
)
GO
INSERT INTO dbo.TB1( C1, C2 )
SELECT 1,1
UNION
SELECT 2,2
UNION
SELECT 3,3
UNION
SELECT 4,4
GO

事务1开始执行,修改数据行但未提交;
BEGIN TRAN
UPDATE dbo.TB1
SET C1=11
WHERE C1=1

在新会话中事务2执行
UPDATE TB1
SET C2=2
WHERE C1=11

2>事务1执行 UPDATE TB1 SET C1=11 WHERE C1=1(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=1,数据行在事务1更新前满足事务2的更新条件,但数据行在事务1更新后又不满足事务2的更新条件,事务2会被事务1阻塞么?

测试结果:会被阻塞

测试代码:

DROP TABLE dbo.TB1
GO
CREATE TABLE TB1
(
    C1 INT,
    C2 INT
)
GO
CREATE UNIQUE CLUSTERED  INDEX IDX_C1
ON dbo.TB1
(
    C1
)
GO
INSERT INTO dbo.TB1( C1, C2 )
SELECT 1,1
UNION
SELECT 2,2
UNION
SELECT 3,3
UNION
SELECT 4,4
GO

事务1开始执行,修改数据行但未提交;
BEGIN TRAN
UPDATE dbo.TB1
SET C1=11
WHERE C1=1

在新会话中事务2执行
UPDATE TB1
SET C2=2
WHERE C1=1

3>事务1执行 INSERT INTO dbo.TB1( C1, C2 )SELECT 5,5(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=5,数据行在事务1更新前满足事务2的更新条件,但数据行在事务1更新后又不满足事务2的更新条件,事务2会被事务1阻塞么?

测试结果:会被阻塞

测试代码:

DROP TABLE dbo.TB1
GO
CREATE TABLE TB1
(
    C1 INT,
    C2 INT
)
GO
CREATE UNIQUE CLUSTERED  INDEX IDX_C1
ON dbo.TB1
(
    C1
)
GO
INSERT INTO dbo.TB1( C1, C2 )
SELECT 1,1
UNION
SELECT 2,2
UNION
SELECT 3,3
UNION
SELECT 4,4
GO

事务1开始执行,修改数据行但未提交;
BEGIN TRAN
INSERT INTO dbo.TB1( C1, C2 )
SELECT 5,5

在新会话中事务2执行
UPDATE TB1
SET C2=2
WHERE C1=5

测试结论:

对于未提交事务A修改的数据,无论该数据在更新修改的值前还是修改后的值满足事务B的修改条件,那么都会对事务B造成阻塞。

--==========================================================

年关近了,日子不好过,随时担心被母亲大人电话轰炸,压力山大,so,小伙伴们就将就着看着没啥营养的博客吧!

--==========================================================

依旧是妹子

时间: 2024-10-17 16:03:47

曲苑杂坛--DML操作中如何处理那些未提交的数据的相关文章

曲演杂坛--一条DELETE引发的思考

原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID INT IDENTITY(1,1) PRIMARY KEY, DT DATETIME ) 每次业务想要获取一个新ID,就执行以下SQL: INSERT INTO TB001(DT) SELECT GETDATE(); SELECT @@IDENTITY 由于这些数据只需保留最近一天的数据,因此建立一个SQL作业来定期删除数据,删除脚

曲演杂坛--收缩数据库数据文件

--===================================================================== 部分朋友在遇到收缩数据库文件的时候遇到一些困难,发现明明有大量剩余空间或删除了大量数据,还是无法收缩数据库,这是为啥子呢? --==================================================================== 要收缩数据库文件,首先我们需要确定有多少空间可以收缩,由于收缩文件是按照Extent来收缩

曲演杂坛--页拆分2

在上次的曲演杂坛--页拆分中基于SQL SERVER 2008版本进行了测试,在SQL Server 2012和SQL Server 2014版本中,对页拆分进行了优化,避免了一次插入导致多次页拆分的情况. 让我们在SQL Server 2014版本中来测试下: --========================================= --使用TestDB数据库来测试 USE TestDB GO DROP TABLE TB01 GO --======================

曲演杂坛--使用ALTER TABLE修改字段类型的吐血教训

--===================================================================== 事件起因:开发发现有表插入数据失败,查看后发现INT类型自增值已经到了最大值,无法继续插入,需要修改INT类型为BIGINT类型. --===================================================================== 作为一群自认为还算有点经验的老DBA,大家相互商量下,决定删除复制,然后禁止访问

曲演杂坛--蛋疼的ROW_NUMBER函数

使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大家娱乐下. ---====================================================== 问题1:为什么加WHERE条件就慢,不加反而快? 查询SQL: WITH Temp AS( SELECT * , ROW_NUMBER()OVER(ORDER BY T2.

曲演杂坛--查看那个应用连接到数据库

在做数据库迁移或其他维护的时候,需要应用端暂停访问,我们可以通过视图查看到连接到数据的IP,对于ADO.NET访问的话,我们还可以查看到连接过来的应用名称,但是对于JAVA程序使用JDBC来访问时,我们就很难知道具体是哪个应用程序在访问我们的数据库,尤其是应用服务器上运行着很多的应用的时候,我们该如何去做呢? --============================================= 首先对于ADO.NET的访问,通过以下代码 SELECT [net_ip].session_

曲演杂坛--表变量的预估行数

在讨论临时表和表变量的区别时,其中一个重点就是两者的预估行数,在默认设置下,表变量的预估行数总是为1,而临时表的预估行数会随表中数据量的变化而变化.正是因为这个区别,在处理大数据量时往往推荐使用临时表而非表变量(当然还有索引的问题). 科普下, 查询优化器会根据预估行数和操作运算符来预估资源消耗,根据资源消耗情况来选取相对“较优”的执行计划,如果预估行数与实际行数差距较大,则可能生成不高效的执行计划. 举个栗子,看着远处的小土包没多远,骑着马跑了半天发现还没到,这就是看山跑死马的典故,如果能相对

曲演杂坛--使用TRY CATCH应该注意的一个小细节

群里一个朋友遇到一个TRY CATCH的小问题,测试后发现是自己从来没有考虑的情况,写篇blog加深下印象 --========================================================= 在MSDN上对TRY CATCH有如下描述: 对 Transact-SQL 实现与 Microsoft Visual C# 和 Microsoft Visual C++ 语言中的异常处理类似的错误处理.Transact-SQL 语句组可以包含在 TRY 块中.如果 TRY

曲演杂坛--特殊字符/生僻字与varchar

对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时varchar类型在存放英文字符和数字时比nvarchar节省一半的存储空间,因此很多DBA都习惯使用varchar类型来存放字符数据,但这样便存在一些乱码隐患! 首先是特殊字符如上下标或版权字符,测试Code如下: --准备测试表 DROP TABLE TB1 GO CREATE TABLE TB1