【发布时间】:2017-07-03 20:11:42
【问题描述】:
假设我们有 Order_Header 和 Order_LineItems 表的常见情况。 另外,假设我们有用于创建、更新和选择订单的交易。喜欢:
创建:
BEGIN TRANSACTION
INSERT INTO Order_Headers...
SET @Id = SCOPE_IDENTITY()
INSERT INTO Order_LineItems...(using @Id)
DECLARE @SomeVar INT
--just example to show update dependant on select
SELECT @SomeVar = COUNT(*) Order_Headers
WHERE OrderDate > '1-1-2017'
UPDATE Order_Headers
SET SomeValue = @SomeVar
WHERE Id = @Id
COMMIT
END TRANSACTION
另一方面,我们有基于某些标准获取订单的交易,为简单起见,假设是最后 10 个:
SELECT TOP 10 * FROM Order_Headers
ORDER BY Id DESC
有人能说出每个事务的正确隔离级别是什么,并简要解释一下原因吗?
[更新]
我想确保没有其他会话可以插入匹配的行 WHERE OrderDate > '1-1-2017'
我还想确保第二笔交易(纯选择订单)永远不会选择在第一笔交易中未完全“完成”的行。意思是那些在事务 INSERT 部分中创建但尚未在 UPDATE 部分中更新的那些。 (我猜这是默认的 READ COMMITED 所涵盖的,对吧?)
[更新 2]
我想要
WHERE OrderDate > '1-1-2017'
成为交易开始时的价值。
【问题讨论】:
-
你要防范什么?您是否要确保在您提交之前没有其他数据库会话可以为
@Ids 插入 Order_LineItems?是否要阻止其他人在您提交之前插入匹配WHERE OrderDate > '1-1-2017'的行? -
添加到@BenGribaudo,问题,您希望
WHERE OrderDate > '1-1-2017'的结果在事务开始时或SELECT查询运行时成为值? -
大家好,感谢两位提出的好问题!我已经更新了我的问题。
-
@deezg,如果您可以确保读取的值在事务开始时,我不确定您为什么要阻止并发会话插入。所需的隔离级别可以通过行版本控制而不是锁定来实现(即 SNAPSHOT 而不是 SERIALIZABLE)。
-
@Dan 好吧,这是个好问题。没有认为它是相关的。实际上,我想要最简单的方法来确保我不会因订单的错误结果而发生冲突。你是对的,如果从事务开始就确保值是 1,那么阻止并发更新就没有意义了。你会如何处理这种情况?您最喜欢的解决方案是什么?
标签: sql sql-server transaction-isolation