我正在尝试使用实体框架进行范围锁定。假设我有一个包含以下列的表:
| Id | int |
| Type | int |
| Value | int |
其中Id
是具有CLUSTERED INDEX的PRIMARY KEY且Type
具有非聚集的NOT-UNIQUE INDEX。
如果我想使用此代码在可序列化事务中选择一个值
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT Value FROM MyTable WHERE Type = 5
SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID AND resource_type = 'KEY'
COMMIT
它正确地锁定了一行Type = 5
和下一行。
如果我执行此查询:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT Id, Type, Value FROM MyTable WHERE Type = 5
SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID AND resource_type = 'KEY'
COMMIT
它锁定所有行。不幸的是,Entity Framwork会选择所有列:
SELECT [Id], [Type], [Value] FROM ...
我正在使用FOREIGN KEY过滤我的真实表格,此列不是唯一的。我试图在Type
列UNIQUE上创建我的非聚集索引,即使我选择了所有列,它也会锁定正确的行。
如何使用NON UNIQUE INDEX?
答案 0 :(得分:1)
锁定的内容取决于查询计划。计划读取的所有内容都需要锁定。因此,您需要让SQL Server找到您想要锁定的索引。首先为该查询创建最佳索引。
为什么要发生特定的锁定模式?如果由于性能原因而完全有效。如果出于行为原因这是非常不可靠的。
您还可以通过不选择实体而不是DTP对象(例如匿名类型)来使EF选择较少的列。
答案 1 :(得分:0)
很遗憾,当WHERE子句包含具有NON-UNIQUE INDEX或NO INDEX的不同列时,SERIALIZABLE事务无法使用Clustered Index进行范围锁定。
我为Entity Framework找到了一个很好的解决方法。
如果要使用特定值锁定ROWS,例如所有Type = FINISHED的行,请创建一个NON-UNIQUE索引(如果该列可以包含重复项)。
我们必须告诉SQL DB我们应该使用哪些INDEX。
// 1
while (listening)
{
TcpClient client = listener.AcceptTcpClient();
// Start a thread to handle this client...
new Thread(() => HandleClient(client)).Start();
}
// 2
while (listening)
{
TcpClient client = listener.AcceptTcpClient();
// Start a task to handle this client...
Task.Run(() => HandleClient(client));
}
// 3
public async void StartListener() //non blocking listener
{
listener = new TcpListener(ipAddress, port);
listener.Start();
while (listening)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);//non blocking waiting
// We are already in the new task to handle this client...
HandleClient(client);
}
}
//... in your code
StartListener();
//...
//use Thread.CurrentThread.ManagedThreadId to check task/thread id to make yourself sure
我使用WITH(INDEX(MyIndex)),所以它锁定Type ='FINISHED'的所有行,即使它有NON-UNIQUE INDEX
也许有人会提供比RAW QUERY更好的解决方案。
编辑:Rangelock使用NON-UNIQUE INDEX没有任何问题。它没有使用,因为数据库中没有足够的数据。