简体   繁体   English

C#、SQLServer - 阻止表行读取,根据需要进行编辑并释放锁

[英]C#, SQLServer - block table row reading, edit if needed and release lock

I need to block database reads on row level while I'm executing update logic for same row.当我为同一行执行更新逻辑时,我需要在行级别阻止数据库读取。 How would nice and clean solution look like?漂亮而干净的解决方案会是什么样子? Here is some code I'm working on:这是我正在处理的一些代码:

using (SqlConnection conn = new SqlConnection(Configuration.ConnectionString)) {
    conn.Open();
    using (SqlTransaction tran = conn.BeginTransaction(IsolationLevel.Serializable)) {
        //TODO lock table row with ID=primaryKey (block other reads and updates)
        using (SqlCommand cmd = new SqlCommand("SELECT Data FROM MyTable WHERE ID=@primaryKey", conn)) { 
            cmd.Parameters.AddWithValue("@primaryKey", primaryKey);
            using (var reader = cmd.ExecuteReader()) {
                data = PopulateData(reader);
            };
        }

        if (isUpdateNeeded(data)) {
            ChangeExternalSystemStateAndUpdateData(data) //EDIT - concurrent calls not allowed
            WriteUpdatesToDatabase(conn, tran, data);    //EDIT
            tran.Commit();
        }


    } //realease lock and allow other processes to read row with ID=primaryKey
}

EDIT:编辑:

I have following constraints:我有以下限制:

  • Code can be executed within different App pools simultaneously.代码可以在不同的应用程序池中同时执行。 So memory lock is not an option所以内存锁不是一种选择
  • ChangeExternalSystemStateAndUpdateData() must be executed only once in the scope of the MyTable row. ChangeExternalSystemStateAndUpdateData() 必须在 MyTable 行的范围内只执行一次。 Concurrent calls will cause problems并发调用会出现问题

Usually the problem here isn't so much row locking , but rather: other SPIDs acquiring read locks between your read and your update - which can lead to deadlock scenarios;通常这里的问题不是行锁定,而是:其他 SPID 在您的读取和更新之间获取读取锁 - 这可能导致死锁情况; the common fix here is to acquire a write lock in the initial read:这里的常见解决方法是在初始读取中获取锁:

SELECT Data FROM MyTable WITH (UPDLOCK) WHERE ID=@primaryKey

Note that if another SPID is explicitly using NOLOCK then they'll still blitz past it.请注意,如果另一个 SPID 明确使用NOLOCK那么它们仍会闪过它。

You could also try adding ROWLOCK , ie WITH (UPDLOCK, ROWLOCK) - personally I'd keep it simple initially.您也可以尝试添加ROWLOCK ,即WITH (UPDLOCK, ROWLOCK) - 我个人最初会保持简单。 Since you're in a serializable context, trying to be too granular may be a lost cause - key-range locks, etc.由于您处于可序列化的上下文中,因此尝试过于细化可能是失败的原因 - 键范围锁等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM