wns*_*349 5 sql sql-server deadlock jdbc
我在SQL Server 2012中遇到了死锁情况.
运行SQL Server Profiler后,我得到一个死锁图如下:
将鼠标移到进程(椭圆形)上时,两个进程都显示相同的PrepareStatement查询(我正在使用JDBC).
我正在使用的查询如下:
MERGE INTO MA4TB_MT_LOG_MSG USING (VALUES (1)) AS S(Num) ON ( MSG_ID = ? )
WHEN MATCHED THEN
UPDATE SET
DIST_DATE = ?,
DIST_CODE = ?
WHEN NOT MATCHED THEN
INSERT (
MSG_ID, DIST_DATE, DIST_CODE
) VALUES (
?,?,?
);
Run Code Online (Sandbox Code Playgroud)
困扰我的是Key lock资源框下的Index name.
我在MA4TB_MT_LOG_MSG表下没有名为"1"的索引.
MSG_ID是MA4TB_MT_LOG_MSG的主键,DIST_DATE,DIST_CODE上没有索引.
关于这种僵局情况的任何形式的建议将不胜感激.
提前致谢,
让我们开始回答你的第一个问题。我没有索引 id = 1。
是的你是!!
让我们看一下 SQL Server 2014 CTP2 上的 Adventure Works 2012 数据库。这是我的笔记本电脑规格。
有一个表名称 [AWBuildVersion]。它有一个聚集索引,就像您的表一样。在索引下,我们可以看到 PK 正在显现。如果我们获取表的对象 ID (sys.objects) 并查找索引条目 (sys.indexes),我们可以看到索引位于位置 1。
简而言之,主键默认是聚集索引。
http://technet.microsoft.com/en-us/library/ms177443(v=sql.105).aspx
好吧,那么没有索引的表有什么呢?这些表称为堆。他们确实在位置 0 处有自己的索引,指向第一个 IAM 页面。
http://technet.microsoft.com/en-us/library/ms188270(v=sql.105).aspx
下面的代码创建一个名为 [crafty] 的架构,并使用 SELECT INTO 将 [AWBuildVersion] 表复制到新架构。SELECT INTO 的好处是不会保留任何索引。
use AdventureWorks2012
go
create schema [crafty] authorization [dbo];
go
select * into crafty.awbuildversion from dbo.awbuildversion
go
Run Code Online (Sandbox Code Playgroud)
简而言之,我们可以看到在位置 0 处用索引定义的堆。
那么什么是死锁,请求模式U是什么意思呢?
死锁是指两个进程同时获取资源但顺序不同。简而言之,这两个过程都无法进行。引擎选择回滚时间最少的会话并终止该进程。
http://technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx
一张图片胜过千言万语!事务 1 获取资源 1。事务 2 获取资源 2。当它们尝试获取彼此的资源时,就会产生死锁。
那么按键锁和用户模式U是什么意思呢?
要更新表,您需要更新数据/索引页。但数据页实际上是表中的索引页(聚集索引)。SQL 引擎取出 (U)PDATE 锁。在实际更新期间,该锁将升级为排它锁(X)。
当两个进程请求独占锁时,就有可能出现死锁。
为了完成这个主题,可以在不阻塞(同时)的情况下执行共享锁(SELECT)。通常,当引擎死锁进程线程检测到循环图时,进程开始阻塞,然后变成死锁。
默认隔离级别是未提交读。
http://technet.microsoft.com/en-us/library/ms175519(v=sql.105).aspx
此时,你陷入了僵局。
你从这里去哪里?
1 - 可能有多个会话 (SPID) 运行相同的代码。为什么?您能否更改此设置,以便一次只有一个进程运行该代码?
2 - 获取 JDBC 生成的实际 TSQL。这可以通过 SQL 探查器和/或查看 DMV 来完成。
merge 语句同时执行 UPDATE 和/或 INSERT。因此是一个复合操作。
3 - 能否将隔离级别更改为可序列化?
http://technet.microsoft.com/en-us/library/ms173763.aspx
这将添加更多的锁,并且可能会将死锁问题变成超时问题。请参阅 Kalen Daleny 文章了解如何设置 LOCK_TIMEOUT。您必须调整代码才能再次重试该操作,中间会有一些延迟。
http://sqlmag.com/sql-server/inside-sql-server-controlling-locking
我希望这些信息对您有所帮助。
如果您需要更多帮助,请发布您的 TSQL。
归档时间: |
|
查看次数: |
919 次 |
最近记录: |