中国开发网: 论坛: 程序员情感CBD: 贴子 592355
李战
是的,锁一般都是为事务服务的。结论只是:表变量的游标无锁
如果没有显式启动事务,则每一个批处理语句将隐式启动一个事务来保证数据完整性。
如果显式启动了事务,则之后发出的每一个批处理语句都处于该事务的保护中。

在事务中,每一次对物理数据的读写操作都会产生相应的锁,有的锁表,有的锁页面,有的甚至锁记录,这些锁将持续到事务提交或回滚时才释放。

因此,批处理语句对表和临时表的读写操作都会产生锁开销。而表变量由于是局部内存数据,主要给批处理语句做高速缓存用的,你既不能把表变量从一个批处理传递给另一个批处理,也无法从一个过程传给另一个过程,而且用户又不可能定义全局变量,更不用说全局表变量。所以,事务也就无须考虑对表变量的共享互斥问题了。

“表变量无锁”

再看游标的情况。所谓游标,不过是一个系统临时创建的索引机制。当我们定义并打开一个可任意滚动的游标时,系统为游标创建了一个以ROWID为主键的聚集索引,再根据基表索引或语句的order by条件创建其他索引,然后填充这些索引。这些索引是存储在临时库中的。游标的初始位置就是当前的ROWID。

而每次调用fetch时,如果只滚动而不取数, 则只将游标位置调整到相应的ROWID;如果还取数据,则不但要调整游标位置,还要根据当前位置的索引信息查找基本的数据并读取。而读取基表时将产生事务的“锁”。对游标的更新也是根据游标当前索引关联基表来实现更新的。

如果把游标定义为只读的,这个游标操作不会更新数据。那么,这样是否就不会产生“锁”呢?

如果不产生锁,当游标要滚动到某位置,而该位置的基表数据却被别的事务删除或修改了,从而无法找到基表对应的记录,这会发生什么情况?

但是,把游标定义为只读并且只进时,执行计划根本看不到在打开游标时建立游标索引的步骤,而每条fetch语句直接是从基表去检索的。因此,这种游标的当前位置只存的基表的一个单一索引值,效率非常的高。

不过,只读只进游标是否确定不会产生“锁”呢?我想也不一定,因为你从这种游标读出数据之后,也可能用于其他更新语句,那么在其他更新语句执行时,相关的数据又已被其他事务更改,是否本事务的完整性还能得到保障呢?

以上问题需要请各位数据库大牛指点啊。

只是,我可以肯定地说:对于表变量(内存表)的游标操作不存在锁开销!
李战(leadzen)

相关信息:


欢迎光临本社区,您还没有登录,不能发贴子。请在 这里登录