Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SqlServer,事务死锁,表实际上是什么时候锁定的?_Sql Server_Transactions - Fatal编程技术网

Sql server SqlServer,事务死锁,表实际上是什么时候锁定的?

Sql server SqlServer,事务死锁,表实际上是什么时候锁定的?,sql-server,transactions,Sql Server,Transactions,从c调用此SQL有时会导致死锁。 服务器负载不大,因此使用的方法是尽可能多地锁定 -- Lock to prevent race-conditions when multiple instances of an application calls this SQL: BEGIN TRANSACTION -- Check that no one has inserted the rows in T1 before me, and that T2 is in a valid

从c调用此SQL有时会导致死锁。 服务器负载不大,因此使用的方法是尽可能多地锁定

   -- Lock to prevent race-conditions when multiple instances of an application calls this SQL:
        BEGIN TRANSACTION 
-- Check that no one has inserted the rows in T1 before me, and that T2 is in a valid state (Test1 != null)
            IF NOT EXISTS (SELECT TOP 1 1 FROM T1 WITH(HOLDLOCK, TABLOCKX) WHERE FKId IN {0}) AND 
            NOT EXISTS(SELECT TOP 1 1 FROM T2 WITH(HOLDLOCK, TABLOCKX) WHERE DbID IN {0} AND Test1 IS NOT NULL) 
            BEGIN
-- Great! Im the first - go insert the row in T1 and update T2 accordingly. Finally write a log to T3 
               INSERT INTO T1(FKId, Status) 
               SELECT DbId, {1} FROM T2 WHERE DbId IN {0}; 

               UPDATE T2 SET LastChangedBy = {2}, LastChangedAt = GETDATE() WHERE DbId IN {0}; 

               INSERT INTO T3 (F1, FKId, F3) 
               SELECT {2}, DbId, GETDATE() FROM T2 WHERE DbId IN {0} ;
            END; 

            -- Select status on the rows so the program can evaluate what just happened
            SELECT FKId, Status FROM T1 WHERE FkId IN {0}; 

        COMMIT TRANSACTION
我认为问题在于需要锁定多个表


我有点不确定什么时候表被真正锁定了——第一次使用表的时候——或者所有表都在BEGIN TRANS一次锁定了吗?

锁定的问题是,您确实需要查看所有同时锁定的位置,没有办法将问题隔离并分成许多较小的问题,并单独研究这些问题

例如,如果其他一些代码锁定了相同的表,但不明显,并且顺序错误,该怎么办?那会导致僵局


您需要在发现死锁的那一刻分析服务器的状态,以试图找出此时还运行着什么。只有这样,您才能尝试修复它。

锁定的问题是,您确实需要同时查看所有锁定的位置,无法将问题隔离并拆分为许多较小的问题,并单独查看这些问题

例如,如果其他一些代码锁定了相同的表,但不明显,并且顺序错误,该怎么办?那会导致僵局


您需要在发现死锁的那一刻分析服务器的状态,以试图找出此时还运行着什么。只有这样才能尝试修复它。

当您调用lock或选择with lock并在提交或回滚时释放时,锁定完成

如果另一个过程先在T3中锁定,然后在T1或T2中锁定,则可能会出现死锁。然后,两个事务等待对方获取资源,同时锁定对方需要的资源


您还可以避免表锁,并使用隔离级别serializable。

当您调用lock或select with lock并在提交或回滚时释放锁时,就会完成锁

如果另一个过程先在T3中锁定,然后在T1或T2中锁定,则可能会出现死锁。然后,两个事务等待对方获取资源,同时锁定对方需要的资源


您还可以避免表锁,并使用隔离级别序列化。

使用表锁会增加死锁的可能性。。。并非所有的死锁都是由无序操作引起的。。。有些可能是由其他活动引起的,这些活动只尝试完全锁定同一个表中的一条记录,因此锁定整个表会增加发生冲突的可能性。当使用可序列化隔离级别时,范围锁被放置在索引行上,这可以防止其他sql操作进行插入/删除,从而导致来自同一过程的两个并发操作发生死锁,即使它们被编码为以相同的顺序执行操作

在任何情况下,要找出导致死锁的确切原因,请设置SQL Server跟踪标志1204和1222。这些将导致在SQL Server日志中写入有关每个死锁的详细信息,包括涉及哪些语句

这是一篇关于如何做到这一点的好文章


完成后不要忘记关闭这些标志…

使用表锁会增加死锁的可能性。。。并非所有的死锁都是由无序操作引起的。。。有些可能是由其他活动引起的,这些活动只尝试完全锁定同一个表中的一条记录,因此锁定整个表会增加发生冲突的可能性。当使用可序列化隔离级别时,范围锁被放置在索引行上,这可以防止其他sql操作进行插入/删除,从而导致来自同一过程的两个并发操作发生死锁,即使它们被编码为以相同的顺序执行操作

在任何情况下,要找出导致死锁的确切原因,请设置SQL Server跟踪标志1204和1222。这些将导致在SQL Server日志中写入有关每个死锁的详细信息,包括涉及哪些语句

这是一篇关于如何做到这一点的好文章


完成后不要忘记关闭这些标志…

此外,如果这是sql server 2005,您可以使用探查器记录死锁&它为您绘制漂亮的图表。此外,如果这是sql server 2005,您可以使用探查器记录死锁&它为您绘制漂亮的图表+1以提及可序列化模式。细粒度的行级锁不太容易受到死锁的影响。是的,从性能角度看,表锁实际上是一件非常糟糕的事情,但是如果它是使事情正常工作的唯一解决方案,那么它就是一个解决方案。+1用于提及可序列化模式。细粒度的行级锁不太容易受到死锁的影响。是的,表锁在性能方面实际上是一件非常糟糕的事情,但是如果它是解决ma的唯一方法的话 如果一切正常,那么这就是一个解决方案。