锁定SQL Server表的C#方法

锁定SQL Server表的C#方法,c#,sql,.net,sql-server,locking,C#,Sql,.net,Sql Server,Locking,我有一个C#程序,需要对SQL Server表执行一组大规模更新(20k+)。由于其他用户可以通过内部网站一次更新一条记录,因此我们需要构建具有锁定表功能的C#程序。一旦表被锁定以防止其他用户进行任何更改/搜索,我们将需要执行请求的更新/插入 由于我们正在处理如此多的记录,我们无法使用TransactionScope(起初似乎是最简单的方法),因为我们的事务最终由。我们需要使用另一种方法 根据我在互联网上读到的内容,使用SqlTransaction对象似乎是最好的方法,但是我无法锁定表。当程序运

我有一个C#程序,需要对SQL Server表执行一组大规模更新(20k+)。由于其他用户可以通过内部网站一次更新一条记录,因此我们需要构建具有锁定表功能的C#程序。一旦表被锁定以防止其他用户进行任何更改/搜索,我们将需要执行请求的更新/插入

由于我们正在处理如此多的记录,我们无法使用
TransactionScope
(起初似乎是最简单的方法),因为我们的事务最终由。我们需要使用另一种方法

根据我在互联网上读到的内容,使用
SqlTransaction
对象似乎是最好的方法,但是我无法锁定表。当程序运行并且我逐步完成下面的代码时,我仍然能够通过intranet站点执行更新和搜索

我的问题有两方面。我是否正确使用了
SqlTransaction
?如果是这样(或者即使不是这样),是否有更好的方法来获取表锁,从而允许当前运行的程序搜索和执行更新

我希望在程序执行下面的代码时锁定表

C#


这里都是关于隔离级别的。将事务隔离级别更改为ReadCommitted(没有在C#中查找枚举值,但应该是关闭的)。当您对表执行第一次更新/插入时,SQL将开始锁定,并且在您提交或回滚thr事务之前,没有人能够读取您正在更改/添加的数据,前提是他们没有执行脏读(在SQL上使用NoLock,或者将连接隔离级别设置为read Uncommited)。。不过要小心,根据插入/更新数据的方式,您可能会在事务期间锁定整个表,但这会导致客户端在事务打开时尝试读取此表时出现超时错误。在没有看到更新背后的SQL的情况下,尽管我无法判断是否会发生这种情况。

尝试这样做:当您从表中获取记录时(在GetRecords()函数中?),使用TABLOCKX提示:

    SELECT * FROM Table1 (TABLOCKX)

它将对事务之外的所有其他读取和更新进行排队,直到事务提交或回滚。

SQL并没有真正提供一种以独占方式锁定表的方法:它的设计目的是在保持ACID的同时尽量提高并发使用率

您可以尝试在查询中使用以下表格提示:

  • 小报

    指定在表级别应用获取的锁。所使用的锁的类型 是否获取取决于正在执行的语句。例如,SELECT语句 可能会获得一个共享锁。通过指定TABLOCK,共享锁将应用于 整个表,而不是行或页级别。如果还指定了HOLDLOCK,则 表锁一直保持到事务结束

  • TABLOCKX

    指定对表使用独占锁

  • 上锁

    指定在事务完成之前获取并保持更新锁。 UPDLOCK仅在行级别或页级别对读取操作使用更新锁。如果 UPDLOCK与TABLOCK结合使用,或者对其他一些应用程序使用表级锁 因此,将采用独占(X)锁

  • XLOCK

    指定在事务处理之前获取并保持独占锁 完成。如果使用ROWLOCK、PAGLOCK或TABLOCK指定,则应用独占锁 到适当的粒度级别

  • 保持锁定/可序列化

    通过将共享锁保留到事务完成,使其更具限制性, 而不是在所需的表或数据页不存在时立即释放共享锁 无论交易是否已完成,都需要更长的时间。扫描是 使用与在可序列化服务器上运行的事务相同的语义执行 隔离级别。有关隔离级别的更多信息,请参见设置事务 隔离级别(Transact-SQL)

或者,您可以尝试将事务隔离级别设置为可序列化:

  • 语句无法读取已修改但尚未由其他语句提交的数据 交易

  • 没有其他事务可以修改当前事务读取的数据 直到当前事务完成

  • 其他事务无法插入包含键值的新行,这些键值将落在 当前事务中任何语句在当前 事务完成

范围锁放置在与的搜索条件匹配的键值范围内 事务中执行的每条语句。这将阻止其他事务更新 或者插入任何符合 当前交易。这意味着如果事务中的任何语句 第二次执行时,它们将读取同一组行。射程锁保持不变 直到事务完成。这是最严格的隔离级别 因为它会锁定整个密钥范围,并在事务处理之前一直保持锁定 完成。由于并发性较低,因此仅在必要时使用此选项。这 选项的作用与在所有SELECT语句中的所有表上设置HOLDLOCK相同 在交易中

但几乎可以肯定的是,锁升级将导致阻塞,您的用户将几乎死在水中(以我的经验)

所以


等待,直到您有一个时间表维护窗口。将数据库设置为单用户模式,进行更改并使其重新联机。

正如有人指出的那样,事务在取出后似乎不会被使用

从有限的信息中,我们知道
    SELECT * FROM Table1 (TABLOCKX)
SqlConnection conn = new SqlConnection();
SqlCommand cmd1 = new SqlCommand();
SqlTransaction tran = conn.BeginTransaction();

...
cmd1.Transaction = tran;
...
tran.Commit();