C# method to lock SQL Server table

前端 未结 4 1580
旧时难觅i
旧时难觅i 2021-02-14 03:29

I have a C# program that needs to perform a group of mass updates (20k+) to a SQL Server table. Since other users can update these records one at a time via an intranet website,

4条回答
  •  闹比i
    闹比i (楼主)
    2021-02-14 03:53

    SQL doesn't really provide a way to exclusively lock a table: it's designed to try to maximize concurrent use while keeping ACID.

    You could try using these table hints on your queries:

    • TABLOCK

      Specifies that the acquired lock is applied at the table level. The type of lock that is acquired depends on the statement being executed. For example, a SELECT statement may acquire a shared lock. By specifying TABLOCK, the shared lock is applied to the entire table instead of at the row or page level. If HOLDLOCK is also specified, the table lock is held until the end of the transaction.

    • TABLOCKX

      Specifies that an exclusive lock is taken on the table.

    • UPDLOCK

      Specifies that update locks are to be taken and held until the transaction completes. UPDLOCK takes update locks for read operations only at the row-level or page-level. If UPDLOCK is combined with TABLOCK, or a table-level lock is taken for some other reason, an exclusive (X) lock will be taken instead.

    • XLOCK

      Specifies that exclusive locks are to be taken and held until the transaction completes. If specified with ROWLOCK, PAGLOCK, or TABLOCK, the exclusive locks apply to the appropriate level of granularity.

    • HOLDLOCK/SERIALIZABLE

      Makes shared locks more restrictive by holding them until a transaction is completed, instead of releasing the shared lock as soon as the required table or data page is no longer needed, whether the transaction has been completed or not. The scan is performed with the same semantics as a transaction running at the SERIALIZABLE isolation level. For more information about isolation levels, see SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

    Alternatively, you could try SET TRANSACTION ISOLATION LEVEL SERIALIZABLE:

    • Statements cannot read data that has been modified but not yet committed by other transactions.

    • No other transactions can modify data that has been read by the current transaction until the current transaction completes.

    • Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.

    Range locks are placed in the range of key values that match the search conditions of each statement executed in a transaction. This blocks other transactions from updating or inserting any rows that would qualify for any of the statements executed by the current transaction. This means that if any of the statements in a transaction are executed a second time, they will read the same set of rows. The range locks are held until the transaction completes. This is the most restrictive of the isolation levels because it locks entire ranges of keys and holds the locks until the transaction completes. Because concurrency is lower, use this option only when necessary. This option has the same effect as setting HOLDLOCK on all tables in all SELECT statements in a transaction.

    But almost certainly, lock escalation will cause blocking and your users will be pretty much dead in the water (in my experience).

    So...

    Wait until you have a schedule maintenance window. Set the database in single-user mode, make your changes and bring it back online.

提交回复
热议问题