【发布时间】:2018-01-09 22:32:55
【问题描述】:
我们有一个使用表 AU_PROCESSQUEUE 进行以下操作的 Java 应用程序:
- 插入新工作
- 将作业状态更新为就绪 |正在运行
- 更新该作业的相关工作流信息
- 作业完成后删除
表 DDL
CREATE TABLE AU_PROCESSQUEUE (
AU_JOB_ID varchar(80) NOT NULL ,
AU_PROCESSFLOW_ID varchar (50) NULL ,
AU_PROCESSFLOW_NAME varchar (64) NULL ,
AU_STATUS varchar (30) NULL ,
AU_SUBJECT varbinary (Max) NULL ,
AU_PROCESSFLOW_OBJECTADDRESS varchar (350) NULL ,
AU_JOB_METADATA varbinary(Max) NULL ,
AU_QUEUE_TIME datetime NULL ,
AU_START_TIME datetime NULL ,
AU_END_TIME datetime NULL ,
AU_INSTANCE_ID varchar (100) NULL ,
AU_PRIORITY numeric(18, 2) NULL ,
AU_NODE_NAME varchar (50) NULL ,
AU_MESSAGE varchar (2000) NULL ,
CONSTRAINT PK_AU_PROCESSQUEUE PRIMARY KEY(AU_JOB_ID)) ;
索引
CREATE NONCLUSTERED INDEX [IX_AU_PROCESSQUEUE_AU_STATUS_AU_NODE_NAME]
ON [AdeptiaBackend].[dbo].[AU_PROCESSQUEUE] (
[AU_STATUS] ASC,
[AU_NODE_NAME] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = ON,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
CREATE NONCLUSTERED INDEX [IX_AU_PROCESSQUEUE_AUQUEUETIME]
ON [AdeptiaBackend].[dbo].[AU_PROCESSQUEUE] (
[AU_QUEUE_TIME] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = ON,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
有一个SELECT 查询会定期在此表上执行以加载按排队时间排序的 QUEUED 作业
Select * from AU_PROCESSQUEUE (NOLOCK)
WHERE (AU_STATUS = 'Queued' OR AU_STATUS = 'Ready To Resume')
and
( AU_NODE_NAME='localhost' OR AU_NODE_NAME IS NULL )
ORDER BY AU_QUEUE_TIME LIMIT 200
Java 应用程序一次只处理固定数量的作业(定义为作业并发,比如 60 个),因此本质上,有 60 个不同的线程并行执行以下查询:
Update AU_PROCESSQUEUE
SET AU_NODE_NAME=@P0 ,
AU_INSTANCE_ID=@P1,
AU_PROCESSFLOW_OBJECTADDRESS=@P2,
AU_STATUS=@P3,
AU_START_TIME=@P4
WHERE AU_JOB_ID=@P5
DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0
问题
在高作业并发下,比如 60,我们看到 SQL Server 中的事务被死锁。这是死锁跟踪:
<deadlock-list>
<deadlock victim="process48d914ca8">
<process-list>
<process id="process4cdda84e8" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="34201" ownerId="1603282" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:31.663" XDES="0x4cdff7770" lockMode="U" schedulerid="1" kpid="3892" status="suspended" spid="122" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:31.663" lastbatchcompleted="2018-01-09T10:12:31.663" lastattention="1900-01-01T00:00:00.663" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1603282" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process48d914ca8" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="35028" ownerId="1603137" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:31.107" XDES="0x488c743b0" lockMode="U" schedulerid="4" kpid="2232" status="suspended" spid="286" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:31.107" lastbatchcompleted="2018-01-09T10:12:31.107" lastattention="1900-01-01T00:00:00.107" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1603137" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4c809dc28" taskpriority="0" logused="0" waitresource="PAGE: 18:1:3620 " waittime="33435" ownerId="1609771" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:57.623" XDES="0x48d905770" lockMode="IU" schedulerid="4" kpid="1712" status="suspended" spid="289" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:57.623" lastbatchcompleted="2018-01-09T10:12:57.620" lastattention="1900-01-01T00:00:00.620" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1609771" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4c7853468" taskpriority="0" logused="0" waitresource="PAGE: 18:1:4688 " waittime="33460" ownerId="1609641" transactionname="UPDATE" lasttranstarted="2018-01-09T10:12:57.237" XDES="0x4c77783b0" lockMode="U" schedulerid="2" kpid="5660" status="suspended" spid="326" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:57.237" lastbatchcompleted="2018-01-09T10:10:20.090" lastattention="1900-01-01T00:00:00.090" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1609641" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="220" stmtend="522" sqlhandle="0x0200000086a2ea1594021304e59bc20f346ab6be8a632b340000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000),@P1 nvarchar(4000),@P2 nvarchar(4000),@P3 nvarchar(4000),@P4 datetime2,@P5 nvarchar(4000))Update AU_PROCESSQUEUE SET AU_NODE_NAME=@P0 , AU_INSTANCE_ID=@P1, AU_PROCESSFLOW_OBJECTADDRESS=@P2, AU_STATUS=@P3, AU_START_TIME=@P4 WHERE AU_JOB_ID=@P5 </inputbuf>
</process>
<process id="process4bd316ca8" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="35028" ownerId="1609113" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:55.737" XDES="0x48d66a3b0" lockMode="U" schedulerid="4" kpid="6312" status="suspended" spid="336" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:55.733" lastbatchcompleted="2018-01-09T10:12:55.733" lastattention="1900-01-01T00:00:00.733" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-7EFMLLQ3PKJ" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1609113" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4bd316108" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="35028" ownerId="1607808" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:51.910" XDES="0x4d1e4a6d0" lockMode="U" schedulerid="4" kpid="9144" status="suspended" spid="266" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:51.910" lastbatchcompleted="2018-01-09T10:12:51.910" lastattention="1900-01-01T00:00:00.910" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1607808" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4bfc37468" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="35029" ownerId="1604201" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:36.360" XDES="0x4b89623b0" lockMode="U" schedulerid="4" kpid="2704" status="suspended" spid="535" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:36.360" lastbatchcompleted="2018-01-09T10:12:36.360" lastattention="1900-01-01T00:00:00.360" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-7EFMLLQ3PKJ" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1604201" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4bd317468" taskpriority="0" logused="0" waitresource="KEY: 18:72057594055098368 (666003c8ddef)" waittime="35029" ownerId="1603983" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:35.400" XDES="0x47ff6c540" lockMode="U" schedulerid="4" kpid="3508" status="suspended" spid="160" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:35.400" lastbatchcompleted="2018-01-09T10:12:35.400" lastattention="1900-01-01T00:00:00.400" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-UOEQMBQP08C" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1603983" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
<process id="process4bd3168c8" taskpriority="0" logused="0" waitresource="PAGE: 18:1:3620 " waittime="8339" ownerId="1598759" transactionname="DELETE" lasttranstarted="2018-01-09T10:12:16.410" XDES="0x491786d90" lockMode="IU" schedulerid="4" kpid="6692" status="suspended" spid="350" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-01-09T10:12:16.410" lastbatchcompleted="2018-01-09T10:12:16.407" lastattention="1900-01-01T00:00:00.407" clientapp="Microsoft JDBC Driver for SQL Server" hostname="WIN-7EFMLLQ3PKJ" hostpid="0" loginname="sa" isolationlevel="read committed (2)" xactid="1598759" currentdb="18" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" stmtend="132" sqlhandle="0x0200000063980b37a86688199d73e7920178af18c95d90030000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 nvarchar(4000))DELETE from AU_PROCESSQUEUE WHERE AU_JOB_ID=@P0 </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process48d914ca8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4cdda84e8" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process4bd3168c8" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process48d914ca8" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<pagelock fileid="1" pageid="3620" dbid="18" subresource="FULL" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" id="lock4af764580" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process4c7853468" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process4c809dc28" mode="IU" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="4688" dbid="18" subresource="FULL" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" id="lock4cfe98600" mode="IU" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process4cdda84e8" mode="IU"/>
<owner id="process4bfc37468" mode="IU"/>
<owner id="process4bd317468" mode="IU"/>
<owner id="process48d914ca8" mode="IU"/>
</owner-list>
<waiter-list>
<waiter id="process4c7853468" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process48d914ca8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4bd316ca8" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process48d914ca8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4bd316108" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process48d914ca8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4bfc37468" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594055098368" dbid="18" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" indexname="IX_AU_PROCESSQUEUE_AUQUEUETIME" id="lock4cfec4f80" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process48d914ca8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4bd317468" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<pagelock fileid="1" pageid="3620" dbid="18" subresource="FULL" objectname="topco_cluster_bk.dbo.AU_PROCESSQUEUE" id="lock4af764580" mode="U" associatedObjectId="72057594055098368">
<owner-list>
<owner id="process4c809dc28" mode="IU" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process4bd3168c8" mode="IU" requestType="wait"/>
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
</deadlock-list>
问题
- 当
UPDATE和DELETE查询都在WHERE子句中使用PK 执行时,为什么我会看到死锁? PK上的更新和删除不是最好的方案吗? - 如果我将 PK(AU_JOB_ID 列)改为 INT(或 BIGINT)而不是 VARCHAR,会有帮助吗?
- 如果我更改状态列 (AU_STATUS) 以引用查找代码,这是否会有所帮助 - 这会将列从 VARCHAR 更改为 INT 并有助于更快地进行比较和搜索?
我不是数据库和 SQL Server 方面的专家,因此我们将不胜感激。提前致谢!
【问题讨论】:
-
来吧格式,这样我们就不必向右滚动一英里
-
@Paparazzi:谢谢你的建议,我已经改进了格式。
-
如果您认为它们是“幻象”冲突,您可以切换到事务隔离级别 SERIALIZABLE。
-
可能不是幻象碰撞。当从聚集索引中删除一行时,它也必须在 AU_QUEUE_TIME 从索引中删除。因此,它将为已删除行查找 AU_QUEUE_TIME 值的索引,并且需要读取(使用 U 锁)具有相同 AU_QUEUE_TIME 的所有索引键以找到它需要删除的索引键。
标签: sql-server database indexing database-deadlocks locks