SELECT FOR UPDATE与SQL Server
我正在使用隔离级别为READ_COMMITTED
和READ_COMMITTED_SNAPSHOT=ON
的Microsoft SQL Server 2005数据库。
现在我想用:
SELECT * FROM <tablename> FOR UPDATE
...以便在尝试访问同一行“FOR UPDATE”时阻塞其他数据库连接。
我试过了:
SELECT * FROM <tablename> WITH (updlock) WHERE id=1
...但是,即使选择了“1”以外的其他连接,也会阻止其他连接。
正如Oracle,DB2,MySql已知的,执行SELECT FOR UPDATE
的正确提示是什么?
编辑2009-10-03:
这些是创建表和索引的语句:
CREATE TABLE example ( Id BIGINT NOT NULL, TransactionId BIGINT,
Terminal BIGINT, Status SMALLINT );
ALTER TABLE example ADD CONSTRAINT index108 PRIMARY KEY ( Id )
CREATE INDEX I108_FkTerminal ON example ( Terminal )
CREATE INDEX I108_Key ON example ( TransactionId )
很多并行进程都是这样做的SELECT
:
SELECT * FROM example o WITH (updlock) WHERE o.TransactionId = ?
编辑2009-10-05:
为了更好地概述,我已经在下表中写下了所有尝试过的解决方案:
mechanism | SELECT on different row blocks | SELECT on same row blocks -----------------------+--------------------------------+-------------------------- ROWLOCK | no | no updlock, rowlock | yes | yes xlock,rowlock | yes | yes repeatableread | no | no DBCC TRACEON (1211,-1) | yes | yes rowlock,xlock,holdlock | yes | yes updlock,holdlock | yes | yes UPDLOCK,READPAST | no | no I'm looking for | no | yes
最近我有一个死锁问题,因为Sql Server锁定更多然后必要(页面)。 你不能对此做任何事情。 现在我们捕捉到了死锁例外......我希望我有Oracle。
编辑:我们同时使用快照隔离,它可以解决很多问题,但不是所有问题。 不幸的是,为了能够使用快照隔离,它必须被数据库服务器所允许,这可能在客户站点造成不必要的问题。 现在我们不仅捕获死锁异常(当然还会发生),还包括快照并发问题,以便从后台进程重复事务(用户不能重复)。 但是这仍然比以前表现得更好。
我有一个类似的问题,我想只锁定1行。 据我所知,使用UPDLOCK
选项,SQLSERVER会锁定所有需要读取的行以获取行。 因此,如果您未定义索引来直接访问该行,则所有先前的行都将被锁定。 在你的例子中:
假设你有一个名为TBL的表和id
字段。 你想锁定id=10
的行。 您需要为字段ID(或您选择的任何其他字段)定义索引:
CREATE INDEX TBLINDEX ON TBL ( id )
然后,您的查询仅锁定您读取的行:
SELECT * FROM TBL WITH (UPDLOCK, INDEX(TBLINDEX)) WHERE id=10.
如果不使用INDEX(TBLINDEX)选项,则SQLSERVER需要从表的开头读取所有行以查找id=10
行,以便这些行将被锁定。
您无法同时进行快照隔离和阻止读取。 快照隔离的目的是防止阻塞读取。
链接地址: http://www.djcxy.com/p/5613.html