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