Sql 通过故意设计的+高度并发的事务最小化死锁?

Sql 通过故意设计的+高度并发的事务最小化死锁?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我目前正在对SQLServer2008中的不同隔离级别进行基准测试,但现在我陷入了一个看似微不足道的死锁问题,但我似乎无法解决它。希望这里有人能给我一些建议,我是SQL的新手 我目前有两种类型的事务来演示脏读,但这与此无关: 事务类型A:从表A中选择所有行 事务类型B:在表A的所有行中设置值“成本”=0,然后立即回滚 我目前运行一个包含1000个线程和10000个事务的线程池,每个线程在执行事务类型a和事务类型B之间随机选择。然而,即使使用强制行锁定,我也会遇到大量死锁 我假设死锁的发生是因为所

我目前正在对SQLServer2008中的不同隔离级别进行基准测试,但现在我陷入了一个看似微不足道的死锁问题,但我似乎无法解决它。希望这里有人能给我一些建议,我是SQL的新手

我目前有两种类型的事务来演示脏读,但这与此无关:

事务类型A:从表A中选择所有行

事务类型B:在表A的所有行中设置值“成本”=0,然后立即回滚

我目前运行一个包含1000个线程和10000个事务的线程池,每个线程在执行事务类型a和事务类型B之间随机选择。然而,即使使用强制行锁定,我也会遇到大量死锁

我假设死锁的发生是因为所获取的锁的行顺序——也就是说,如果A型和B型“扫描”表A的顺序相同,例如从上到下,则此类死锁不会发生。但是,我很难弄清楚如何让SQLServer在SELECT和UPDATE语句期间维护行顺序

有什么建议吗?第一次贴到stackoverflow的海报,请温柔:-

编辑:故意将隔离级别设置为READ_COMMITTED,以表明它消除了脏读,并且确实如此。死锁只发生在等于或高于READ_COMMITTED的任何级别上;显然,未提交的READ_上不会发生死锁


编辑2:这些事务正在SQL Server 2008R2上的AdventureWorks LT的新实例上运行。

如果要启动事务以更新所有行,请键入B,然后回滚事务,则需要为所有行上的整个事务保持锁定。即使您有行级锁,也需要为整个事务保留该锁

如果您有页级或表级锁定,您可能会看到较少的死锁,因为Sql Server更容易处理这些死锁,但是在事务进行期间,您仍然需要在整体上保持这些锁

在设计高度并发的系统时,应该避免锁定整个表的查询。我建议使用以下MicroSoft指南来了解锁并减少其影响:


如果要启动一个事务以更新所有行,键入B,然后回滚该事务,则需要为所有行上的整个事务保留锁。即使您有行级锁,也需要为整个事务保留该锁

如果您有页级或表级锁定,您可能会看到较少的死锁,因为Sql Server更容易处理这些死锁,但是在事务进行期间,您仍然需要在整体上保持这些锁

在设计高度并发的系统时,应该避免锁定整个表的查询。我建议使用以下MicroSoft指南来了解锁并减少其影响:


为了澄清,我的理解是:如果XACT A以递增方式选择行,而XACT B以递减方式更新行,则可能会发生死锁,例如:XACT A获得第1行的锁;XACT A获得第2行的锁,放弃第1行的锁;XACT B获得第3行的锁,想要访问第2行,但被阻止;XACT A希望访问第3行,但被阻止。但是,如果XACT A和XACT B以相同的顺序遍历行,显然这种死锁不会发生。我该如何实施这一点?能否从SQL Profiler中提供包含索引和死锁图的表结构?为了澄清这一点,我的理解是:如果XACT A以递增的方式选择行,而XACT B以递减的方式更新行,则可能会发生死锁,例如:XACT A获取行1上的锁;XACT A获得第2行的锁,放弃第1行的锁;XACT B获得第3行的锁,想要访问第2行,但被阻止;XACT A希望访问第3行,但被阻止。但是,如果XACT A和XACT B以相同的顺序遍历行,显然这种死锁不会发生。我如何执行此操作?能否从SQL Profiler中提供包含索引和死锁图的表结构?我简化了我的“应用程序”以执行同一个查询:更新表A,其中rowID='123'。然而,每当我在隔离级别设置为READ_COMMITTED或更高的情况下同时运行300多个这样的查询时,就会出现死锁问题。此外,行锁定/表锁定提示仍然会出现错误!有趣的是,即使在快照隔离上,我仍然会遇到这些SQL异常,据我所知,快照隔离不使用锁。实际上,我有一种感觉,这可能是由于某些其他资源而不是锁导致了死锁。通过SQL事件探查器生成的死锁图显示了被划掉的受害进程,该进程连接到一个线程池,然后该线程池连接到数百个其他进程。没有提到任何锁。你可以看到图表
这里:我简化了我的“应用程序”以执行同一个查询:更新表A,其中rowID='123'。然而,每当我在隔离级别设置为READ_COMMITTED或更高的情况下同时运行300多个这样的查询时,就会出现死锁问题。此外,行锁定/表锁定提示仍然会出现错误!有趣的是,即使在快照隔离上,我仍然会遇到这些SQL异常,据我所知,快照隔离不使用锁。实际上,我有一种感觉,这可能是由于某些其他资源而不是锁导致了死锁。通过SQL事件探查器生成的死锁图显示了被划掉的受害进程,该进程连接到一个线程池,然后该线程池连接到数百个其他进程。没有提到任何锁。您可以在此处看到图表: