当我们进行DML操作(insert update delete)时,会在对应表上添加DML lock。DML_LOCKS参数规定了dml lock的最大数量。默认情况下,dml_locks的取值为TRANSACTION参数的4倍,即其假设每个事务平均操作4张表。
SQL> show parameter transaction
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
transactions integer 281
transactions_per_rollback_segment integer 5
SQL> show parameter dml_locks
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dml_locks integer 1124
SQL> alter system set transactions=300;
alter system set transactions=300
*
第 1 行出现错误:
ORA-02095: 无法修改指定的初始化参数
SQL> alter system set transactions=300 scope=spfile;
系统已更改。
SQL> startup force
ORACLE 例程已经启动。
Total System Global Area 2137886720 bytes
Fixed Size 2230072 bytes
Variable Size 1593837768 bytes
Database Buffers 536870912 bytes
Redo Buffers 4947968 bytes
数据库装载完毕。
数据库已经打开。
SQL> show parameter dml
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dml_locks integer 1200
当然,我们也可以手工指定DML_LOCKS的值,此时不再受transactions参数的影响
SQL> alter system set dml_locks=100 scope=spfile;
系统已更改。
SQL> startup force
ORACLE 例程已经启动。
Total System Global Area 2137886720 bytes
Fixed Size 2230072 bytes
Variable Size 1593837768 bytes
Database Buffers 536870912 bytes
Redo Buffers 4947968 bytes
数据库装载完毕。
数据库已经打开。
SQL> show parameter transactions
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
transactions integer 300
transactions_per_rollback_segment integer 5
SQL> show pamameters dml_locks
SP2-0158: 未知的 SHOW 选项 "pamameters"
SP2-0158: 未知的 SHOW 选项 "dml_locks"
SQL> show parameter dml_locks
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dml_locks integer 100
dml_locks参数是一个软设置,即实际使用的DML LOCKS可以超过DML_LOCKS的设置,如下实例,我们另外启动两个session,分别操作一张表,则
SQL> alter system set dml_locks=1 scope=spfile;
系统已更改。
SQL> startup force
ORACLE 例程已经启动。
Total System Global Area 2137886720 bytes
Fixed Size 2230072 bytes
Variable Size 1593837768 bytes
Database Buffers 536870912 bytes
Redo Buffers 4947968 bytes
数据库装载完毕。
数据库已经打开。
SQL> select * from v$resource_limit where resource_name='dml_locks';
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE
------------------------------ ------------------- --------------- -------------------- --------------------
dml_locks 1 1 1 UNLIMITED
SQL> /
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE
------------------------------ ------------------- --------------- -------------------- --------------------
dml_locks 2 2 1 UNLIMITED
SQL> show parameter dml_locks
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dml_locks integer 1
这里有一点需要特别注意,就是当我们将DML_LOCKS设置为0时,DML LOCK enqueues是被禁止的,因此在很大程度上可以提供系统的性能,但是会存在如下限制:
1.我们不可以进行DROP TABLE,CREATE INDEX等操作,但是可以create table(create table不需要DML LOCK)
2.不可以手动执行表级别的锁定,例如LOCAK TABLE IN EXCLUSIVE MODE
3.不可以使用em
例如:
session 1
SQL> alter system set dml_locks=0 scope=spfile;
系统已更改。
SQL> startup force
ORACLE 例程已经启动。
Total System Global Area 2137886720 bytes
Fixed Size 2230072 bytes
Variable Size 1593837768 bytes
Database Buffers 536870912 bytes
Redo Buffers 4947968 bytes
数据库装载完毕。
数据库已经打开。
SQL> show parameter dmls_locks
SQL> show parameter dml_locks
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dml_locks integer 0
SQL> select * from v$resource_limit where resource_name='dml_locks';
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE
------------------------------ ------------------- --------------- -------------------- --------------------
dml_locks 0 0 0 UNLIMITED
session 2
SQL> create table tab3 (id number,name varchar2(10));
表已创建。
SQL> insert into tab3 values(1,1);
已创建 1 行。
SQL> commit;
提交完成。
SQL> drop table tab3;
drop table tab3
*
第 1 行出现错误:
ORA-00062: 无法获得 DML 全表锁定; DML_LOCKS 为 0
session 2:此时并没有提交
SQL> insert into tab3 values(2,2);
已创建 1 行。
SQL> select * from tab3;
ID NAME
---------- ----------
1 1
2 2
session 1
SQL> l
1* select * from v$resource_limit where resource_name='dml_locks'
SQL> /
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE
------------------------------ ------------------- --------------- -------------------- --------------------
dml_locks 0 0 0 UNLIMITED