我有一个长时间运行的插入事务,它将数据插入到几个相关的表中。
当此插入运行时,我无法从MainTable执行select *。选择只是旋转它的轮子直到插入完成。
我将在相同/重叠时间执行其中几个插入。要检查信息是否未插入两次,我首先查询MainTable以查看是否存在条目并且未设置其已处理的位。
在插入事务期间,它会翻转该行的MainTable处理位。
所以我需要能够读取表格,并且能够判断特定行当前是否正在更新。
有关如何在Microsoft SQL 2005中进行此设置的任何想法?我正在查看SET TRANSACTION ISOLATION LEVEL文档。
谢谢你,
基思
编辑:我认为同一插入批次不会同时发生。这些是正在处理的二进制文件,其数据已插入数据库。在解析和插入数据之前,我检查文件是否尚未处理。当我进行检查时,如果在我快速插入MainTable并且处理的位设置为false之前没有看到该文件。
有没有办法锁定正在更新的行而不是整个表?
答案 0 :(得分:2)
您可能需要在使用READ UNCOMMITTED之前重新考虑您的过程。隔离交易有很多充分的理由。如果您使用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
答案 1 :(得分:0)
允许一个事务读取正在进行的另一个事务(在提交之前)执行的更改的唯一隔离级别是:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED