3

我刚刚意识到我根本不了解 .NET/SQL Server 事务是如何工作的。我觉得我可能会把信封推到“没有愚蠢的问题”,但我读过的所有文档都不容易理解。我将尝试以这样一种方式来表达这个问题,答案几乎是是/否。

如果我在一台有效执行此操作的机器上运行 .NET 进程(不是真正的代码):

For i as Integer = 0 to 100
    Using TransactionScope
        Using SqlClient.SqlConnection
            'Executed using SqlClient.SqlCommand'
            "DELETE from TABLE_A"
            Thread.Sleep(5000)
            "INSERT INTO TABLE_A (Col1) VALUES ('A')"
            TransactionScope.Complete()
        End Using
    End Using
Next i

是否有任何事务/隔离级别配置会使“SELECT count(*) FROM TABLE_A”在从其他进程运行时始终返回“1”(即即使表中没有行时有 5 秒的时间块在交易的背景下)?

4

3 回答 3

1

是的,您可以让其他进程看不到您在所示事务中所做的更改。为此,您需要更改其他进程,而不是进行修改的进程。

打开快照隔离并IsolationLevel.Snapshot在其他读取进程上使用。他们将在您进行任何修改之前看到该表的状态。他们不会阻止(等待)。

于 2012-10-04T21:51:03.843 回答
1

SNAPSHOT 隔离是您要找的。假设当您开始循环时该表有一行,在 SNAPSHOT 隔离级别下运行的并发 SELECT 将始终看到 1 行,无论何时运行,而无需等待

除 READ UNCOMMITTED 外,所有其他隔离级别也将始终准确看到 1 行,但通常会阻塞长达 5 秒。请注意,我将 READ_COMMITTED_SNAPSHOT 视为此参数的 SNAPSHOT。

脏读,即。在 READ UNCOMMITTED 隔离级别下运行的 SELECT 将有 0、1 甚至2行。没错,脏读可能会看到 2 行,即使您从未一次插入 2 行,这是因为 SELECT 的扫描点和事务的插入点之间的竞争条件,请参阅如果 NOLOCK 可能会错过先前提交的行提示用于类似的问题讨论。

于 2012-10-04T21:53:28.010 回答
0

我相信默认事务超时为 1 分钟(请参阅:http: //msdn.microsoft.com/en-us/library/ms172070.aspx),因此在您的事务上下文中,我认为您期望该表是正确的在插入之前没有记录(无论暂停如何),因为每个命令将在事务中按顺序完成,这将是删除的结果。

希望有帮助。

于 2012-10-04T21:44:59.490 回答