Python SQL Server中针对表并发运行的脚本
我需要在多个服务器上运行相同的Python脚本,所有这些脚本都针对DB服务器上的同一个表。脚本运行需要5-20秒,并且必须每5分钟运行一次Python SQL Server中针对表并发运行的脚本,python,sql,sql-server,concurrency,isolation-level,Python,Sql,Sql Server,Concurrency,Isolation Level,我需要在多个服务器上运行相同的Python脚本,所有这些脚本都针对DB服务器上的同一个表。脚本运行需要5-20秒,并且必须每5分钟运行一次 Server1 ---> ------------- | DB Table | Server2 ---> ------------- 脚本将查看一个如下所示的表: Type | many other fields | DirtyBit | Owner ---------------------------
Server1 ---> -------------
| DB Table |
Server2 ---> -------------
脚本将查看一个如下所示的表:
Type | many other fields | DirtyBit | Owner
--------------------------------------------
X | ... | UnUsed | NULL
X | ... | UnUsed | NULL
X | ... | UnUsed | NULL
Y | ... | UnUsed | NULL
Y | ... | UnUsed | NULL
begin transaction;
select * from test where DirtyBit = 'UnUsed' and Owner is null (TABLOCKX);
update test set DirtyBit = 'Used', Owner = 'Server1' where id in (...);
commit;
该脚本执行以下操作:
DirtyBit
为UnUsed
且Owner
为NULL
的X类型(在事务中)的所有记录DirtyBit
设置为InUse
,将Owner
设置为Server1
DirtyBit
设置回UnUsed
,并将Owner
设置回NULL
我不会采取你在这里使用的方法。像这样的本土解决方案往往很脆弱
对于a来说,这似乎是一个好问题,通过以下方式控制并发性:开发基于并发访问和修改数据的解决方案始终是一件非常明智的事情。他们也容易犯错误,这些错误很少发生,而且很难找到 在您的情况下,实际上,您要做的是序列化对表的访问,而不仅仅是更新。也就是说,只允许一个线程(事务)获取它需要的数据(其中,
DirtyBit
是UnUsed
,而Owner
是NULL
),并将这些行标记为“used”。我很确定您当前的解决方案不能正常工作。为什么?考虑这样一个场景:
Type | many other fields | DirtyBit | Owner
--------------------------------------------
X | ... | UnUsed | NULL
X | ... | UnUsed | NULL
X | ... | UnUsed | NULL
Y | ... | UnUsed | NULL
Y | ... | UnUsed | NULL
begin transaction;
select * from test where DirtyBit = 'UnUsed' and Owner is null (TABLOCKX);
update test set DirtyBit = 'Used', Owner = 'Server1' where id in (...);
commit;
在这里,(TABLOCKX)
将导致其他事务等待该事务提交或回滚-它们将无法读取数据。这能解决你的问题吗
但是。。。如果您可以在这个特定的情况下避免并发,我建议您这样做(因为我的回答的第一段) 你能评论/推测一下你认为这个特殊的解决方案在哪里是脆弱的吗?我认为计划作业不适合这种情况,因为脚本在数据库之外做了很多工作。我一定会尝试一下
sp_getapplock
,如果这个答案可行的话,我会接受它。谢谢。您在事务中运行四个步骤中的哪一个?它们都在一个事务中,每一步都在单独的事务中,还是以另一种方式?您使用什么事务隔离级别?因此,当我在开始选择所有行时,我可以简单地使用TABLOCKX
,在这种情况下,没有理由使用Owner
或DirtyBit
来控制并发性,我可以删除这些列。正确吗?TABLOCKX
设置表锁,直到事务结束。这意味着,如果要在事务中执行耗时的操作,则整个表将对其他事务保持锁定-它们将等待并可能耗尽事务时间。我认为最好是在一个事务中获取行并更新表(描述中的前两个步骤),然后在第一个事务之外对脚本中的数据进行操作(这样就不会阻止对表的访问),然后在完成任务后更新表(步骤4)。当然,如果表可以长时间锁定,那么您可以放弃使用这些列。这取决于此表的作用。