oracle数据库:锁和闩_笔记9
如何用数据本身来管理锁定和事务信息。这是块开销的一部分。现在只需知道数据库块的最前面有一个“开销”空间,这里会存放该块的一个事务表。对于锁定了该块中某些数据的各个“实际”事务,在这个事务表中都有一个相应的条目。这个结构的大小由创建对象时CREATE语句上的两个物理属性参数决定。
.INITRANS:这个结构初始的预分配大小。对于索引和表,这个大小默认为2。
.MAXTRANS:这个结构可以扩展到的最大大小。它默认为255,在实际中,最小值为2。在Oracle Database 10g及更高版本中,这个设置已经废弃了,所以不再使用。这个版本中的MAXTRANS总是255。
默认情况下,每个块最开始都有两个事务槽。一个块上同时的活动事务数受MAXTRANS值的约束,另外也受块上空间可用性的限制。如果没有足够的空间来扩大这个结构,块上就无法得到255个并发事务。
我们可以通过手工操作来说明这里的原理。首先创建一个表,其中包含大量的行,而且都压入一个块,使这个块从一开始就非常满,初始加载数据之后这个块上只留下极小的空间。这些行的存在会限制事务表的增长,原因就在于缺少空间。
下面首先创建这个装满数据的表。
SQL> create table t
2 (x int primary key,
3 y varchar2(4000)
4 )
5 /
Table created.
SQL> insert into t (x,y)
2 select rownum,rpad('*',148,'*')
3 from dual
4 connect by level <=46;
46 rows created.
SQL> select length(y),
2 dbms_rowid.rowid_block_number(rowid) blk,
3 count(*),min(x),max(x)
4 from t
5 group by length(y),dbms_rowid.rowid_block_number(rowid);
LENGTH(Y) BLK COUNT(*) MIN(X) MAX(X)
---------- ---------- ---------- ---------- ----------
148 266681 46 1 46
SQL>
所以,我们的表有46行,所有这些行都在同一个块上。之所以选择148个字符,是因为如果再多一个字符,就需要两个块才能存放同样的这46条记录。现在,需要想办法查看多个事务试图同时锁定这个块上的数据时会发生什么。
为此,我们再次使用一个AUTONOMOUS_TRANSACTION,这样就能使用一个会话,而不必运行大量并发的SQL*Plus会话。我们的存储过程会按主键锁定表中的一行,从主键值1开始。如果我们的过程得到这一行的锁而不必等待,它将把主键值增1,并利用递归反复做同样的事情。所以第二次调用会试图锁定记录2,第三次调用会锁定记录3,依此类推。如果要求过程等待,它会产生一个“ORA-54资源忙”错误,我们会打印“locked out trying to select row
create or replace procedure do_update(p_n in number)
as
pragma autonomous_transaction;
l_rec t%rowtype;
resource_busy exception;
pragma exception_init(resource_busy,-54);
begin
select *
into l_rec
from t
where x=p_n
for update NOWAIT;
do_update(p_n+1);
commit;
exception
when resource_busy
then
dbms_output.put_line('locked out trying to select row' || p_n);
commit;
when no_data_found
then
dbms_output.put_line('we finished-no problems');
commit;
end;
/
(怎么没有exception)
如果共发事务数量过多,就要等待事务表。类似地,如果INITRANS设置得很低,而且块上没有足够的空间来动态地扩展事务,也会出现阻塞。大多数情况下,INITRANS的默认值2就足够了,因为事务表会动态扩大(只要空间允许)。但是在某些环境中,可能需要加大这个设置来提高并发性,并减少等待。
比如,在频繁修改的表上就可能要增加INITRANS设置,或者更常见的是,对于频繁修改并且平均每块有许多行的索引也可能需要这么做,因为索引块中的行一般比表中的行多。可能需要增加PCTFREE或INITRANS,从而在块上提前预留足够的空间以应付可能的并发事务数。尤其是,如果你预料到块开始时几乎是满的(这说明块上没有空间来动态扩展事务结构),则更需要增加PCTFREE或INITRANS。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5201.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
