我有一个长期运行的插入事务,它将数据插入到几个相关的表中。
当这个插入正在运行时,我无法从MainTable执行select*。选择只旋转轮子,直到插入完成。
我将在同一时间/重叠时间执行其中的几个插入。为了检查信息是否没有插入两次,我首先查询MainTable,看看是否有条目,以及是否没有设置其处理位。
在插入事务期间,它翻转该行的MainTable处理位。
因此,我需要能够读取该表,并且能够判断特定行当前是否正在更新。
关于如何在MicrosoftSQLServer2005中进行设置,有什么想法吗?我正在查看SET TRANSACTION ISOLATION LEVEL文档。
谢谢,
Keith
编辑:我不认为同一插入批次会同时发生。这些是正在处理的二进制文件,它们的数据被插入到数据库中。在解析和插入数据之前,我会检查文件是否尚未处理。当我进行检查时,如果之前没有看到文件,我会在处理后的位设置为false的情况下快速插入到MainTable中。
有没有办法锁定正在更新的行而不是整个表?
在使用READ UNCOMITTED之前,您可能需要重新思考您的流程。孤立事务有很多很好的理由。如果使用READ UNCOMMITTED,您可能仍然会得到重复项,因为两个插入项都有可能同时检查更新,但都找不到它们,从而创建重复项。尝试将其分解为较小的批次或定期发布COMMITS
编辑
您可以将MainTable更新封装在事务中,这样可以更快地释放该表,但仍可能与其他表发生冲突。
即
BEGIN TRANSACTION
SELECT @ProcessedBit = ProcessedBit FROM MainTable WHERE ID = XXX
IF @ProcessedBit = False
UPDATE MainTable SET ProcessedBit = True WHERE ID = XXX
COMMIT TRANSACTION
IF @ProcessedBit = False
BEGIN
BEGIN TRANSACTION
-- start long running process
...
COMMIT TRANSACTION
END
编辑以启用错误恢复
BEGIN TRANSACTION
SELECT @ProcessedStatus = ProcessedStatus FROM MainTable WHERE ID = XXX
IF @ProcessedStatus = 'Not Processed'
UPDATE MainTable SET ProcessedBit = 'Processing' WHERE ID = XXX
COMMIT TRANSACTION
IF @ProcessedStatus = 'Not Processed'
BEGIN
BEGIN TRANSACTION
-- start long running process
...
IF No Errors
BEGIN
UPDATE MainTable SET ProcessedStatus = 'Processed' WHERE ID = XXX
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
END
允许一个事务读取另一个正在进行的事务执行的更改(在提交之前)的唯一隔离级别是:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED