为什么使用 .net 并行更新数据库会导致一致的结果

Why Parallel update database with .net leads to consistent result

我正在尝试运行以下代码以在并行更新数据库(使用多个线程)时显示“不一致”,但是当我运行此代码时 table 总是一致的,即 500。它是如何工作的?

static void Main(string[] args)
    for (int i = 0; i < 500; i++) {
        Thread t = new Thread(() => Update());
        t.Start();
    }

    await Task.Delay(100000);
}

public static void Update() {
    using (var conn = new SqlConnection("mssql-connection-string")) {
        conn.Execute("update [table] set counter = counter +1;");
    }
}

您拥有的代码不会导致竞争条件,因为您想要 UPDATE 的行将被锁定、递增,然后释放锁;这意味着任何其他试图同时成为 运行 的 UPDATE 语句将不得不“等待” first UPDATE 完成.

如果要模拟竞态条件,先给一个变量赋值;那应该给你行为:

DECLARE @c int = (SELECT counter FROM dbo.[table]); --I assume table only has 1 row
UPDATE dbo.[table] SET Counter = @c + 1;

这意味着 counter 的值将首先分配给变量,这不会锁定其他进程读取它的行。因此,多个并发线程可能同时读取该行,然后 UPDATE 将其设为各自的 +1 值。因此,5 个线程可能都将值读取为 7,并且将 UPDATE 的值读取为 7+1 (8).

如果出于某种原因,您确实需要先将 table 中的值赋值给一个变量,然后再 UPDATE 它们,那么您需要使用 UPDLOCK 在您的查询中提示:

DECLARE @c int = (SELECT counter FROM dbo.[table] WITH (UPDLOCK)); --I assume table only has 1 row
UPDATE dbo.[table] SET Counter = @c + 1;

您可能还需要将事务的隔离级别更改为 SERIALIZABLE