UPDATE 时, 如何避免数据定位处理被阻塞

问题描述:<o:p></o:p>

数据库PUBS中的authors表,想锁定CITYaaa的记录,为什么执行下面的命令后,CITYbbb的记录也被锁定了,无法进行UPDATE.<o:p></o:p>

BEGIN TRANSACTION     <o:p></o:p>

    SELECT * FROM authors <o:p></o:p>

    WITH (HOLDLOCK) <o:p></o:p>

    WHERE city='aaa' <o:p></o:p>

如何才能锁定CITYAAA的记录,而且CITYBBB的记录依然能SELECTUPDATE<o:p></o:p>

<o:p> </o:p>

问题分析:<o:p></o:p>

应该不是被锁住,应该只是检索数据的时候,需要从aaa的记录扫描到bbb的记录,而aaa被锁住了,所以扫描无法往下进行,这样看起来似乎就是bbb也被锁住了。<o:p></o:p>

当然,也有可能确实是被锁住了,SQL Server的锁定默认是行级的,如果你的资源不足,则可能导致锁自动升级为页级甚至表级锁,这样会导致更多的记录被锁定。<o:p></o:p>

使用下面的语句, 如果能读出数据, 则多半是第1种情况.<o:p></o:p>

SELECT * <o:p></o:p>

FROM authors WITH (READPAST) <o:p></o:p>

WHERE city='bbb'<o:p></o:p>

如果读不出数据, 则一般是第2种情况.<o:p></o:p>

<o:p> </o:p>

问题解决方法:<o:p></o:p>

SELECT UPDATE 走不同的索引,这样在UPDATE 的时候,不用扫描已经锁定的数据就可以定义到记录,UPDATE 也就不会被阻塞了<o:p></o:p>

指定索引用类似下面的语句:<o:p></o:p>

SELECT * <o:p></o:p>

FROM authors WITH (HOLDLOCK, INDEX=索引名) <o:p></o:p>

WHERE city='aaa'<o:p></o:p>

<o:p> </o:p>

UPDATE A SET <o:p></o:p>

    xx = xx<o:p></o:p>

FROM authors A WITH (INDEX=索引名) <o:p></o:p>

WHERE city='bbb'<o:p></o:p>

当然,要保证仅扫描索引就可以定义到记录,否则可能还是会被阻塞。<o:p></o:p>

<o:p> </o:p> 

补充<o:p></o:p>

对于熟悉SQL Server锁的读者,可以通过 sp_lock,或者查询系统表 master.dbo.syslocksmaster.dbo.syslockinfo来确定行为。<o:p></o:p>

你可能感兴趣的:(sql,SQL Server)