Monitoring and Detecting Lock Contention

Monitoring and Detecting Lock Contention
 

1、Locking机制
1)Oracle Server中是自动管理锁的。默认会使用最低的锁级别对数据进行一致性的保护,从而满足最大的并发度。
note:默认的锁机制可以通过ROW_LOCKING改变。默认该值是ALWAYS,它将在DML语句中使用最低级别的锁。另一个可能的值是 INTENT,它将使用更高级别的限制(table level),除了select for update语句,它将使用行级锁。
2)quiesced database:如果Oracle被设置为只有DBA可以访问的状态时,就是quiesced database。
3)锁的种类:
**  DML locks
①表级锁(TM):当修改table data时,被设置,如:INSERT, UPDATE, DELETE, SELECT … FOR UPDATE或LOCK TABLE。此时table将被加锁,避免其他DDL的操作引起transaction之间的冲突。
##   在TM中又可分为两种锁,是由server根据当前其他表锁的加载情况而自动为DML选择加上的。这两种锁具体是:row exclusive(RX),运行其他transaction中的insert、update、delete或其他加行级锁的并发操作在当前同一 table上,但不允许其他手动加载的排他读/写锁;row share(RS),运行SELECT … FOR UPDATE命令时加载的表锁,这只会对避免其他事务手动的对当前table加载锁用于排他的写操作。
##   表锁模式:
(i)手动加载表锁模式使用语句LOCK TABLE table_name IN mode_name MODE; –一般不使用这种明确加锁的方法,只有application要求,才会不得不加较高级别的锁。
(ii)Share(S)锁模式:此类表锁只允许其他transaction发出select … from update的请求,不允许任何对table的修改。隐含式的获得share lock的sql语句中,会包含相应的完整性约束。在9i中,不会申请子表中外键字段的索引约束。
(iii)Share Row Exclusive(SRX):它是比S模式更高的锁模式。它不允许任何其他的DML语句和手动加载的共享锁模式。相应的SQL语句会隐式的获得相应的完整性约束的SRX锁。
(iv)Exclusive(X)锁:这是最高的锁模式,只允许其他对该表的查询请求,拒绝一切对表的任何DML操作和手动锁。
②行级锁(TX):当发出命令INSERT, UPDATE, DELETE, SELECT … FOR UPDATE命令时,会自动为所操作的row对象加TX,从而确保没有其他user同时对同一行进行才操作。
一个DML事务,会同时获得两个锁:共享表级锁和排他行级锁。获得行级锁的每行都返回

③在blocks中的DML锁:加锁的信息只有在transaction被commit或是rollback后才会被清除。而不是在当前事务的下一个请求语句发起时被释放。在blocks header中,Oracle server为每个当前active的transaction保存了一个标识符。在每条row中,会有一个lock byte存储了包含当前transaction的slot的标识符。

**  DDL locks避免对schema对象的定义时,有其他相关的DDL操作进行。
Oracle是通过入队的方式对锁进行维护的,入队机制会记录下面的信息:user等待的locks被其他user占用;users请求的locks的具体类型;users请求的locks的顺序。
可以通过改变参数DML_LOCKS和ENQUEUE_RESOURCES参数来增加可被request的locks。这在Parallel server中是必须的设置。DDL锁的分类有:
①Exclusive DDL Locks:某些DDL语句,如CREATE, ALTER, DROP,必须获得其操作object的排他锁。如果其他user获得了其他任何级别的lock,当前user都不能得到其DDL的排他锁。
②Shared DDL locks:当发起GRANT和CREATE PACKAGE操作时,需要获得相应object的共享DDL lock。该类locks不会阻止类似的DDL语句或是任何DML语句,但会防止其他user对当前引用的object被修改或删除。
③Breakable Parse Locks:保存在library cache中的statement和PL/SQL对象保存了其引用的每个object的breakable parse Lock,直到该statement过期。它用于检验library cache中的相应内容是否因为object的改变而可用。

2、可能引起Locks冲突的原因:
1)使用了不必要的high-level锁
2)长期运行的transaction的存在
3)user没有及时的commit对database的修改
4)使用Oracle instance的application使用了higher locks

3、监控并诊断当前加锁情况的工具

1)如上图所示,其中视图DBA_WAITERS和DBA_BLOCKERS用于进一步查看当前获得或是等待不同table的locks的信息。对此,需要用$ORACLE_HOME/rdbms/admin中的catblock.sql脚本创建。
2)对于v$lock视图来说,当lock tpye为TX时,id1中显示的回滚段的number和slot number;当lock tpye为TM时,id1中显示的是被修改表的object ID。
SELECT owner, object_id, object_name, object_type, v$lock.type FROM dba_objects, v$lock WHERE object_id=v$lock.id1 and object_name=table_name;
3)V$LOCKED_OBJECT视图
XIDUSN:Rollback segment number
OBJECT_ID:ID of the object being modified
SESSION_ID:ID of the session locking the object
ORACLE_USERNAME
LOCKED_MODE
在此视图中,当XIDUSN为0时,则表示当前session正在等他其他已经获得该lock的session释放。
4)关于脚本utllockt.sql
可以使用$ORACLE_HOME/rdbms/admin/utllockt.sql脚本显示当前等待lock的进程继承关系。但使用之前必须用catblock.sql脚本创建视图dba_locks和dba_blockers。
5)如果想要得知哪一行造成了lock冲突,可以查看v$session中的row_wait_block#, row_wait_row#, row_wait_file#, row_wait_obj#四个字的的值。

4、解决locks的冲突方法有:一方面可以请相应的user做commit/rollback;在万不得已的时候,可以kill掉某些user session,从而回滚相应的transaction并释放locks。具体方法如下:
select sid, serial#, username from v$session where type=’USER’;
alter system kill session ’sid,serial#’;

5、死锁:对于Oracle,当其检测到死锁的存在,会rolling back那个检测到死锁的语句,当不是整个transaction的rollback。必要时,需要DBA完成剩下的rollback工作。明确的指明语 句中使用的锁,从而覆盖默认的锁机制,可能容易引起deadlock。
当发生死锁后,server会将deadlock的情况记录到USER_DUMP_DEST目录下的跟踪文件。在分布式transaction中,本地的 deadlock是通过等待关系图(waits for graph)来判断的,全局死锁是通过time-out来判断的。

你可能感兴趣的:(Monitoring and Detecting Lock Contention)