想象一下我们有常规的Orders_Headers和Orders_LineItems表的情况。还可以说我们有一条特殊的业务规则,其中规定:
每个订单都有“折扣”字段,该字段是根据上次输入的订单所经过的时间计算得出的
如果在过去的Y个小时内有超过X个订单,则将特别计算每个下一个订单折扣字段。
如果最近10个订单的平均频率高于每分钟x,则将特别计算每个下一个订单折扣字段。
每个下一个订单折扣字段是专门计算的
这里的要点是表明每个订单都依赖于先前的订单,隔离级别至关重要。
我们有一个事务(只是所示代码的逻辑):
BEGIN TRANSACTION INSERT INTO Order_Headers... SET @Id = SCOPE_IDENTITY() INSERT INTO Order_LineItems...(using @Id) DECLARE @SomeVar INT --just example to show selecting previous x orders --needed to calculate Discount value for new Order SELECT @SomeVar = COUNT(*) Order_Headers WHERE ArbitraryCriteria UPDATE Order_Headers SET Discount= UDF(@SomeVar) WHERE Id = @Id COMMIT END TRANSACTION
我们还有另一笔交易来读取订单:
SELECT TOP 10 * FROM Order_Headers ORDER BY Id DESC
问题
SNAPSHOT隔离级别是否适用于第一个事务,而READ COMMITED是否适用于第二个适当级别?
有没有更好的方法来处理CREATE / UPDATE事务,或者这是做到这一点的方法?
该serializable选项:
serializable
通过updlock和serializable表提示使用悲观锁定策略来获取由where条件指定的键范围锁定(由支持索引支持以仅锁定查询所需的范围):
updlock
where
declare @Id int, @SomeVar int; begin tran; select @SomeVar = count(OrderDate) from Order_Headers with (updlock,serializable) where OrderDate >= '20170101'; insert into Order_Headers (OrderDate, SomeVar) select sysdatetime(), @SomeVar; set @Id = scope_identity(); insert into Order_LineItems (id,cols) select @Id, cols from @TableValuedParameter; commit tran;