1

G'day

我想我对可序列化有误解。我有两个表(数据、事务),我将信息插入到可序列化事务中(它们要么都在,要么都在外面,但不在边缘)。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
INSERT INTO dbo.data (ID, data) VALUES (@Id, data)
INSERT INTO dbo.transactions(ID, info) VALUES (@ID, @info) 
COMMIT TRANSACTION

我有一个协调查询,它检查数据表中没有处于读取提交隔离级别的事务的条目。

INSERT INTO reconciles (ReconcileID, DataID) 
SELECT Reconcile = @ReconcileID, ID FROM Data 
WHERE NOT EXISTS (SELECT 1 FROM TRANSACTIONS WHERE data.id = transactions.id)

请注意,ID 实际上是一个复合(2 列)键,所以我不能使用 NOT IN 运算符

我的理解是,第二个查询将排除任何写入数据的值而没有它们的事务,因为此插入发生在可序列化时,而读取发生在读取提交时。

因此,我所看到的是,当使用此查询输入时,Reconcile 查询已获取数据表中但不在事务表中的数据条目,由于隔离级别,我认为这是不可能的。

4

1 回答 1

4

所有事务隔离级别都专门针对读取。没有“可序列化”插入,就像没有“读提交”插入一样。写入永远不会受到序列化级别的影响。将两个插入包装到序列化级别(任何级别)中是无操作的,因为插入在所有隔离级别下的行为都相同。

INSERT ... SELECT ...另一方面,第二个查询通过包含读取(SELECT),隔离级别的影响。SELECT 部分将根据当前隔离级别(在本例中为已提交读)运行。

事务中的更新 写入仅在提交之后才在事务外部可见。如果您有一个序列begin transaction; insert into A; insert into B; commit,那么至少处于读取提交隔离状态的读取器将不会在插入 B 之前看到插入 A。如果您的协调查询看到部分事务(即看到插入 A w/oa 相应的插入进入 B) 那么你有一些可能的解释:

  • 协调查询以错误的隔离级别运行并进行脏读
  • 该应用程序确实分别提交了两个插入
  • 应用程序中的代码缺陷导致仅插入 A

最可能的解释是最后一个。

于 2010-06-09T06:01:38.273 回答