首页 > 解决方案 > 如何设置正确的交易级别?

问题描述

我在 ADO.NET 上使用 Dapper。所以目前我正在做以下事情:

using (IDbConnection conn = new SqlConnection("MyConnectionString")))
{
conn.Open());
using (IDbTransaction transaction = conn.BeginTransaction())
{
// ...

但是,可以设置各种级别的事务。我认为这是各种设置。

我的第一个问题是如何设置事务级别(我在哪里使用 Dapper)?

我的第二个问题是以下每种情况的正确级别是多少?在每种情况下,我们都有多个正在运行的 Web Worker (Azure) 服务实例,它们将同时访问数据库。

  1. 我需要按月收取订阅费用。因此,在交易中,我需要读取一条记录,如果需要支付费用,请创建发票记录并将记录标记为已处理。出于相同目的对该记录的任何其他读取都需要失败。但是任何其他仅使用它来验证它是否处于活动状态的记录都需要成功。

那么,我将使用什么事务来更新已处理列的访问权限?对于只需要验证记录是否处于活动状态的其他访问,我使用什么事务?

在这种情况下,如果冲突导致充电无法运行,那很好(我们将在第二天得到它)。但至关重要的是,我们不要向某人收取两次费用。当另一个操作在其事务中时,验证记录是否处于活动状态的读取立即成功是至关重要的。

  1. 我需要更新仅设置几列的记录。一个用例是我为用户记录设置了一个新的密码哈希。如果在此期间除了删除记录之外发生其他访问,那很好(我认为这是唯一有问题的用例)。如果另一个 Web 服务也在更新,那是用户同时在 2 个地方执行此操作的问题。

但关键是记录保持一致。这包括“set NumUses = NumUses + @ParamNum”的用例,因此它需要将列值的读取、计算、写入视为原子操作。如果我设置 3 个列值,它们都会被写在一起。

标签: sql-serverado.netdapperisolation-level

解决方案


1)假设发票过程是一个带有多个语句的 SP,你最好的办法是创建另一个“锁定”表来存储发票作业已经在运行的事实,例如

CREATE TABLE InvoicingJob( JobStarted DATETIME, IsRunning BIT NOT NULL )

-- Table will only ever have one record
INSERT INTO InvoicingJob
SELECT NULL, 0


EXEC InvoicingProcess

ALTER PROCEDURE InvoicingProcess
AS
BEGIN
    DECLARE @InvoicingJob TABLE( IsRunning BIT )

    -- Try to aquire lock
    UPDATE InvoicingJob WITH( TABLOCK )
    SET JobStarted = GETDATE(), IsRunning = 1
    OUTPUT INSERTED.IsRunning INTO @InvoicingJob( IsRunning )
    WHERE IsRunning = 0
        -- job has been running for more than a day i.e. likely crashed without releasing a lock
        -- OR ( IsRunning = 1 AND JobStarted <= DATEADD( DAY, -1, GETDATE()) 

    IF NOT EXISTS( SELECT * FROM @InvoicingJob )
    BEGIN
        PRINT 'Another Job is already running'
        RETURN
    END
    ELSE
        RAISERROR( 'Start Job', 0, 0 ) WITH NOWAIT


    -- Do invoicing tasks
    WAITFOR DELAY '00:01:00' -- to simulate execution time

    -- Release lock
    UPDATE InvoicingJob
    SET IsRunning = 0
END

2) 了解事务的工作原理:https ://docs.microsoft.com/en-us/sql/t-sql/language-elements/transactions-transact-sql?view=sql-server-2017

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017

你的第二个问题很广泛。


推荐阅读