ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 锁--DDL锁和闩

锁--DDL锁和闩

原创 Linux操作系统 作者:xw_z 时间:2009-07-22 11:00:27 0 删除 编辑
  • DDL

    1> 作用:在DDL操作中会自动为对象加DDL锁,从而保护这些对象不会被其他会话所修改。

    2> DDL语句执行期间会一直持有DDL锁,一旦操作执行就立即释放DDL锁。实际上,通常会把DDL语句包装在隐式提交(或提交/回滚对)中来执行这些工作。在Oracle中,DDL一定会提交,每条CREATE ALTER等语句实际上都如下执行(伪代码):

    Begin

      Commit;

      DDL-STATEMENT

      Commit;

  •        Exception

                   When others then roolback;

      End;

      3> 三种DDL

      1)排他DDL锁(Exclusive DDL lock):防止其他会话得到它们自己的DDL锁或TMDML)锁。这说明,在DDL操作期间,你可以查询一个表,但是无法以任何方式修改这个表。

      2)共享DDL锁(Shared DDL lock):这些锁会保护所引用对象的结构,使之不会被其他会话修改,但是允许修改数据。

      3)可中断解析锁(Breakable parse locks):这些锁允许一个对象(如共享池中缓存的一个查询计划)向另外某个对象注册其依赖性。如果在被依赖的对象上执行DDLOracle会查看已经对该对象注册了依赖性的对象列表,并使这些对象无效。因此,这些锁是“可中断的”,它们不能防止DDL出现。

      4> 例:

      1)大多数DDL都带有一个排他DDL锁,如:

      alter table t add new_colunm date;

      2)有些DDL操作没有DDL锁也可以发生,如:

      create index t_idx on t(x) ONLINE;

      说明:Oracle并不是加一个排他DDL锁来防止数据修改,而只会试图得到表上的一个低级(mode 2TM锁。这会有效防止其他DDL发生,同时还允许DML正常进行。

      3)在创建存储的编译对象(如过程和视图)时,会对依赖的对象加这种共享DDL锁。如:

      create view MyView

      as

        select *

        from emp,dept

        where emp.deptno = dept.deptno;

    说明:表EMPDEPT都会加共享DDL锁,而CREATE VIEW命令仍在处理。可以修改这些表的内容,但是不能修改它们的结构。

    4)会话解析一条语句时,对于该语句引用的每一个对象都会加一个解析锁。目的是:如果以某种方式删除或修改了一个被引用的对象,可以将共享池中已解析的缓存语句置为无效(刷新输出)。可通过DBA_DDL_ LOCKS查看共享池中锁定的对象。如:

      create or replace procedure p as begin null; end;
      Procedure created.

      exec p;
      PL/SQL procedure successfully completed.

      select session_id sid,owner,name,type,mode_held held,mode_requested request from dba_ddl_locks;

      此时过程P在过程中出现。

      alter procedure p compile;
      Procedure altered.

      select session_id sid,owner,name,type,mode_held held,mode_requested request from dba_ddl_locks;

      重新编译过程P后,它从DBA_DDL_LOCKS视图中消失,说明解析锁被中断了。

    • 闩(latch

      1> 闩是轻量级的串行化设备,用于协调对共享数据结构、对象和文件的多用户访问。闩是一种锁,设计为只保持极短的一段时间(例如,修改一个内存中数据结构所需的时间)。闩用于保护某些内存结构,如数据库块缓冲区或共享池中的库缓存。

      2> 一般会在内部以一种“愿意等待”模式请求闩。这说明,如果闩不可用,请求会话会睡眠很短的一段时间,并在以后再次尝试这个操作。还可以采用一种“立即”模式请求其他闩。闩释放后,紧接着不论哪个会话请求闩都会得到它。等待闩的会话不会排队,只是一大堆会话在不断的重试。

      3> 由于设置和释放闩的指令是原子性的,尽管可能有多个进程在同时请求它,但操作系统本身可以保证只有一个进程能测试和设置闩。闩只保持很短的时间,而且提供了一种清理机制,万一某个闩持有者在持有闩时异常地“死掉了”,就由PMON执行清理。

      4> 与队列锁的区别:队列锁是一种更复杂的串行化设备,它允许请求者“排队”等待资源。对于闩请求,请求者会话会立即得到通知是否得到了闩。而对于队列锁,请求者会话会阻塞,直至真正得到锁。队列锁没有闩快,但能提供闩所没有的一些功能(如共享锁)。

      5> 闩“自旋”(spin

      1)如果闩不是立即可用的,我们就得等待,在一台多CPU机器上,我们的会话就会自旋,即:在循环中反复尝试来得到闩。出现自旋的原因是:上下文切换(即进程被“踢出”CPU,然后又必须调度回CPU)的开销很大,所以如果进程不能立即得到闩,我们就会一直呆在CPU上,并立即再次尝试,而不是先睡眠,放弃CPU,等到必须调度回CPU时才再次尝试。之所以呆在CPU上,是因为我们指望闩的持有值正在另一个CPU上忙于处理(由于闩设计为只保持很短的时间),而且会很快放弃闩。如果出现自旋并不断地尝试想得到闩,但是之后还是得不到闩,此时我们的进程才会睡眠,或者让开CPU,而让其他工作进行。

      2> 得到一个闩的开销不只是“测试和设置”操作这么简单,我们尝试得到闩时,可能会耗费大量的CPU时间。系统看上去很忙(因为消耗了很多CPU时间),但是并没有作多少实际的工作。例如我们通过比较两个程序来研究闩定共享池的开销,其中好的程序使用了绑定变量,而不好的程序中每条语句使用了SQL直接量或各不相同的SQL。对于未使用绑定变量的程序:同时运行这样的两个程序耗费的CPU时间是只运行一个这样的程序耗费的CPU时间的3倍而不是2倍;对于使用绑定变量的程序:同时运行这样的两个程序耗费的CPU时间是只运行一个这样的程序耗费的CPU时间的22.5倍。这是因为不使用绑定变量则增加了硬解析SQL的次数,而我们需要闩定共享池来解析SQL语句,所以就增加了等待闩的时间,把一部分CPU时间浪费在闩的自旋上。

    • 手动锁定和用户定义锁

      1> 更新一个表时,Oracle 会为它加一个 TM ,以防止其他会话删除这个表(实际上,也会防止其他会话对这个表执行大多数 DDL) 。在我们修改的各个块上会加上 TX ,这样就能告诉别人哪些数据是“我们的”。数据库采用 DDL 锁来保护对象,这样当我们正在修改这些对象时,别人不会同时对它们进行修改。数据库在内部使用了闩和锁(lock)来保护自己的结构。

      2> 通过一条SQL语句手动地锁定数据:如select for update或使用LOCK TABLE语句。

      3> 通过DBMS_LOCK包创建我们自己的锁。

    来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17014649/viewspace-609871/,如需转载,请注明出处,否则将追究法律责任。

    上一篇: 锁类型--DML锁
    下一篇: 并发与多版本
    请登录后发表评论 登录
    全部评论

    注册时间:2009-05-22

    • 博文量
      28
    • 访问量
      38707