2011-03-28 81 views
6

我目前正在SQL Server 2008数据库上进行一些实验。更具体地讲,我有一个使用数百个并发线程的执行数千个任务JDBC应用程序,每个运行数据库以下查询:SQL Server 2008:发生死锁...没有任何锁

UPDATE from Table A where rowID='123' 

但是,我得到一吨的死锁错误的( SQL异常1205),只要我将隔离级别设置为高于READ_UNCOMMITTED。即使我设置了行锁定,表锁定和排他锁提示,它也会发生!即使在不使用锁的快照隔离中,我仍然会遇到死锁错误。

我通过SQL Profiler运行了一个跟踪,以便在发生这种情况时获取死锁图形,但它没有多大用处。它显示受害者进程连接到一个“线程池”,连接到数百个其他进程。您可以点击此处查看:

http://i.stack.imgur.com/7rlv3.jpg

没有人有任何线索,为什么发生这种情况?在过去的几天里,我一直在疯狂地试图找出答案。我目前的假设是,它与我的数据库实例中可用的工作线程,可用内存量或与实际查询级别锁无关的事情有关。

谢谢!

+0

[看过这个了吗?](http://blogs.msdn.com/b/bartd/archive/2008/09/24/today-s-annoyingly-unwieldy-term-intra-query-parallel-thread- deadlocks.aspx)你的更新语句是否有一个并行计划? – 2011-03-28 21:32:43

+0

你是说''READ_UNCOMMITTED'生效时,这些死锁**永远不会发生?对我来说,这并不明显,这将如何影响所显示的'update'语句。 – 2011-03-28 21:41:08

+0

哇!在这么短的时间内,我并不期待这种压倒性的反应!在READ_UNCOMMITTED下仍然会发生死锁,但是只有当有很多很多并发线程正在进行时(大约为1000),才会发生死锁。我对这种模糊性表示歉意。 – akwok 2011-03-28 23:27:02

回答

1

像这样的死锁/锁是奇怪的,并指向SQL服务器以外的东西。值得的是,我们遇到了很多死锁问题,结果是磁盘瓶颈!

我建议你运行perfmon(显然在那之后有很多其他的工具),看看它是如何做的。

1

你不能做任何事情 SQL Server的无锁 - 即使NOLOCK陈述贴满将发布在最低限度模式锁和大概几页锁最基本的查询。

为了解决死锁问题,您需要获取T1204死锁跟踪(有关更多详细信息,请参阅Deadlock Troubleshooting, Part 1),其中将列出死锁中涉及的确切锁和对象 - 这应该有足够的信息来解决头部划伤的数量)到底发生了什么问题。

没有完全了解死锁背后的原因更改隔离级别,似乎一点点危险,我...

作为一种预感这让我想起一个问题,我有一个几年前的 - 是UPDATE声明死锁针对SELECT声明? (T1024跟踪会告诉你这个)你有没有非聚集索引rowID?如果是这样,你可能想看看this MSDN article,特别是示例6:非聚簇索引。如果不是,那么请继续阅读该文章,因为它可能有助于解释其他一些相关的死锁情况,如果需要帮助分析它,还会发布T1024跟踪结果。

6

你遇到了一个更深奥的野兽:资源死锁。你有什么线程比不能产生子任务(sys.dm_os_tasks)来执行它的工作,因为所有的工人(sys.dm_os_workers)都很忙。反过来,忙碌的工作人员执行被受害者阻止的任务,可能在普通锁上。

有两个教训我在这里看到的带回家:

1)您发布的更新是试图去平行。如果更新与您发布的完全相同,则意味着唯一一件事:rowId上没有索引。

2)您已在max worker threads设置的上限上反弹。难怪,考虑到您滥用客户端中的线程(hundreds of concurrent threads to execute thousands of task),并且由于不必要的并行性而在服务器中将其倍增。

一个明智的设计将真正的异步连接(AsynchronousProcessing=true)上使用异步执行(BeginExecuteNonQuery),并使用未决请求池,因此不会去超过一定的阈值。更可能的情况是,您将通过table valued parameter传入整批更新值,然后通过单个语句更新整批或多批的行。我知道我的所有链接都是针对.Net,而不是针对Java,我不在乎,你可以自己挖掘出相应的Java功能。

因此,虽然有趣的是,你发现了这样一个深奥的僵局,它只会显示出来,因为你的设计,以及...糟透了。

+1

我会为+1进行精彩的分析..但是用-1来锻炼,我们应该说,交货吗?省略2个字左右会读取..更好? – RichardTheKiwi 2011-03-28 23:02:49

+1

感谢您的回复,Remus。我明白这个设计太糟糕了,但它是有目的地完成的!我正在开发一个应该显示以下内容的项目:1.)根据所选隔离级别的类型,存在不同的读取异常,并显示2.)经验性性能命中选择隔离级别,限制并发性而不是必要。无论如何,你的评论确实是有道理的,我会更多地研究它。至少你能够为我提供一个方向来进一步阅读:-) – akwok 2011-03-28 23:29:47

+0

@akwok:我明白了。考虑到UPDATE必须首先找到要更新的行,然后更新它们。 'find'部分*受隔离级别的影响。即使REPEATABLE_READ也可以选择以高粒度锁定级别(页面,表格)进行扫描。要考虑的第二件事是'更新'部分将与所有隔离级别下的另一更新(包括快照)发生冲突。此外,由于散列冲突,*不同*行的更新将会发生冲突:http://rusanu.com/2009/05/29/lockres-collision-probability-magic-marker-16777215/ – 2011-03-28 23:59:35