在Oracle 11g中,lock机制进一步增强,主要体现在如下3个方面
- Serializing Locks
- Locking Tables Explicitly
- Sharing Locks
Serializing Locks
也有人把这个特性归纳为DDL Wait选项.在一个Prod Database中,DBA尝试更改名为 SALES 的表,为其添加一列 TAX_CODE。这是很常见的任务,当执行了类似以下 SQL 语句:
SQL> alter table sales add (tax_code varchar2(10));
往往我们会遇到这样的错误,而非“Table altered”之类的内容:
alter table sales add (tax_code varchar2(10)) * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
错误消息描述的是:该表目前可能正由一个事务使用,因此要获得该表的独占锁定不太可能。当然,表的行不会永远锁定。当会话执行提交动作后,会释放对这些行的锁定,但在此之前,由于解除锁定期间很长,其他会话可能会更新表的其他行 — 这样,获得表的独占锁定的时机又消失了。在典型的商务环境中,以独占方式锁定表的窗口会定期打开,但 DBA 可能无法恰好在那时执行 alter 命令。
当然,DBA也可以反复键入相同的命令,直到获得独占锁定或者失败(两者取其先)。
在 Oracle 数据库 11g 中,DBA有更好的选择:DDL Wait 选项。她可以执行以下命令:
SQL> alter session set ddl_lock_timeout = 10; Session altered.
现在,如果会话中的 DDL 语句没有获得独占锁定,也不会显示错误消息。相反,它将等待 10 秒钟。在这 10 秒钟内,它将不断重试 DDL 操作,直到成功或超时(两者取其先)。如果执行以下命令:
SQL> alter table sales add (tax_code varchar2(10));
该语句将挂起,并且不会显示错误消息。这样,DBA 就将重复尝试操作外包给了 Oracle 数据库 11g(就像电话通过程序重试繁忙号码),而不必反复尝试以获得难以捉摸的独占锁定可用时机。
由于在系统繁忙期间更改表时,每个人都遇到过相同的问题,他们都发现这个新特性非常有帮助。因此,DBA很想知道是否可以将该行为设为默认行为,这样就不需要每次都执行 ALTER SESSION 语句?
是的,可以。如果您执行 ALTER SYSTEM SET DDL_LOCK_TIMEOUT = 10,会话将在 DDL 操作期间自动等待该时间段。与任何其他 ALTER SYSTEM 语句一样,该语句可被 ALTER SESSION 语句覆盖。
注:参数DDL_LOCK_TIMEOUT的设置范围是0-1000000 (秒).
Locking Tables Explicitly
我们知道,在Oracle 11前的版本中,当发出一个LOCK TABLE命令时,如果正好有其他session对这个表持有了锁,这时会无限期的等待或是直接不等待(NOWAIT clause )返回一个错误。在11g中,新增的wait option允许一个lock table操作等待一段时间去获取需要的lock直到timeout返回错误,如果在wait的时间段内获得了需要的lock,命令将成功执行。
在11g中,LOCK TABLE这个命令又有了一个新的语法,允许我们指定一个等待DML锁的时间,语法如下:
LOCK TABLE … IN lockmode MODE [NOWAIT | WAIT integer]
Specify NOWAIT if you want the database to return control to you immediately. If the specified table, partition, or table subpartition is already locked by another user, the database returns a message.
Use the WAIT clause to indicate that the LOCK TABLE statement should wait up to the specified number of seconds to acquire a DML lock. There is no limit on the value of the integer. If you specify neither NOWAIT or WAIT, the database waits indefinitely until the table is available, locks it, and returns control to you. When the database is executing DDL statements concurrently with DML statements, a timeout or deadlock can sometimes occur. The database detects such timeouts and deadlocks and returns an error.
■Wait for up to 10 seconds for a DML lock:
LOCK TABLE hr.jobs IN EXCLUSIVE MODE WAIT 10;
■Do not wait if another user already has locked the table:
LOCK TABLE hr.employees IN EXCLUSIVE MODE NOWAIT;
■Lock a table that is accessible through the remote_db database link:
LOCK TABLE hr.employees@remote_db IN SHARE MODE;
Sharing Locks
在11g中,下面的DDL操作不再需要一个独占锁[exclusive locks (X)],而是一个共享锁[exclusive locks (SX)],这样改进的好处就是当执行这些DDL操作的时候不会阻塞DML操作。
– CREATE INDEX ONLINE
– CREATE MATERIALIZED VIEW LOG
– ALTER TABLE ENABLE CONSTRAINT NOVALIDATE
In highly concurrent environments, the requirement of acquiring an exclusive lock for example at the end of an online index creation and rebuild could lead to a spike of waiting DML operations and, therefore, a short drop and spike of system usage. While this is not an overall problem for the database, this anomaly in system usage could trigger operating system alarm levels. This feature eliminates the need row exclusive locks, when creating or rebuilding an online index.