游标并发
Microsoft® SQL Server™ 2000 支持服务器游标的四个并发选项:
- READ_ONLY
- OPTIMISTIC WITH VALUES
- OPTIMISTIC WITH ROW VERSIONING
- SCROLL LOCKS
READ_ONLY
不允许通过游标定位更新,且在组成结果集的行中没有锁。
OPTIMISTIC WITH VALUES
乐观并发控制是事务控制理论的一个标准部分。乐观并发控制用于这样的情形,即在打开游标及更新行的间隔中,只有很小的机会让第二个用户更新某一行。当某个游标以此选项打开时,没有锁控制其中的行,这将有助于最大化其处理能力。如果用户试图修改某一行,则此行的当前值会与最后一次提取此行时获取的值进行比较。如果任何值发生改变,则服务器就会知道其他人已更新了此行,并会返回一个错误。如果值是一样的,服务器就执行修改。
选择这个并发选项将迫使用户或程序员承担责任,处理那些表示其它用户已经对其进行了修改的错误。应用程序收到这种错误时采取的典型措施就是刷新游标,获得其新值,然后让用户决定是否对新值进行修改。在 SQL Server 6.5 版或早期版本中,text、ntext 和 image 列不用于并发比较。
OPTIMISTIC WITH ROW VERSIONING
此乐观并发控制选项基于行版本控制。使用行版本控制,其中的表必须具有某种版本标识符,服务器可用它来确定该行在读入游标后是否有所更改。在 SQL Server 中,这个性能由 timestamp 数据类型提供,它是一个二进制数字,表示数据库中更改的相对顺序。每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有 timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS 值,然后增加 @@DBTS 的值。如果某个表具有 timestamp 列,则时间戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需比较 timestamp 列即可。如果应用程序对没有 timestamp 列的表要求基于行版本控制的乐观并发,则游标默认为基于数值的乐观并发控制。
SCROLL LOCKS
这个选项实现悲观并发控制。在悲观并发控制中,在把数据库的行读入游标结果集时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会在其上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游标,则提取下一行时,锁就被丢弃。因此,每当用户需要完全的悲观并发控制时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,从而阻止其它任务更新该行。然而,更新锁并不阻止共享锁,所以它不会阻止其它任务读取行,除非第二个任务也在要求带更新锁的读取。
滚动锁
根据在游标定义的 SELECT 语句中指定的锁提示,这些游标并发选项可以生成滚动锁。滚动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为准。下次提取时,服务器为新提取中的行获取滚动锁,并释放上次提取中行的滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚操作之后。如果提交时关闭游标的选项为关,则 COMMIT 语句并不关闭任何打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔离。
所获取滚动锁的类型取决于游标并发选项和游标 SELECT 语句中的锁提示。
锁提示 |
只读 |
乐观数值 | 乐观行版本控制 | 锁定 |
---|---|---|---|---|
无提示 | 未锁定 | 未锁定 | 未锁定 | 更新 |
NOLOCK | 未锁定 | 未锁定 | 未锁定 | 未锁定 |
HOLDLOCK | 共享 | 共享 | 共享 | 更新 |
UPDLOCK | 错误 | 更新 | 更新 | 更新 |
TABLOCKX | 错误 | 未锁定 | 未锁定 | 更新 |
其它 | 未锁定 | 未锁定 | 未锁定 | 更新 |
*指定 NOLOCK 提示将使指定了该提示的表在游标内是只读的。
指定游标并发选项
并发选项在每个游标环境下的指定都不同:
- Transact-SQL 游标
在 DECLARE CURSOR 语句中指定 READ_ONLY、SCROLL_LOCK 和 OPTIMISTIC 关键字。OPTIMISTIC 关键字指定乐观行版本控制,Transact-SQL 游标不支持乐观数值并发选项。
- ADO 应用程序
指定 Recordset 对象 LockType 属性中的 adLockReadOnly、adLockPessimistic、adLockOptimistic 或 adLockBatchOptimistic。
- ODBC 应用程序
将语句特性 SQL_ATTR_CONCURRENCY 设置为 SQL_CONCUR_READ_ONLY、SQL_CONCUR_ROWVER、SQL_CONCUR_VALUES 或 SQL_CONCUR_LOCK。
- DB-Library 应用程序
将 dbcursoropen 参数 concuropt 设置为 CUR_READONLY、CUR_OPTCC(用于乐观行版本控制)、CUR_OPTCCVAL 或 CUR_LOCKCC。
请参见
dbcursoropen
http://www.caiblog.com/blog/wells/archive/2005/03/15/89205.html