zoukankan      html  css  js  c++  java
  • oracle锁

    关于锁
    1、TX锁(事务锁)
    create table test2 as select * from gwm_attribute where rownum<5;
    select * from test;
    update test2 set gwm_ano=gwm_ano+10;
    --如果有一个更新行没有提交或回滚,执行如下语句就会看到一个lmode为6,request为0的排他锁;如果在另一个会话中又对这个表执行更新,
    --就会陷入死锁,再执行如下语句就会看到出现两行记录,其中的lmode为0,request为6的就是一个请求排他锁的请求,如果阻止该会话的排他锁提交
    --或回滚,这个请求行就会消失。
    select username,
           v$lock.sid,
           trunc(id1 / power(2, 16)) rbs,
           bitand(id1, to_number('ffff', 'xxxx')) + 0 slot,
           id2 seq,
           lmode,
           request
      from v$lock, v$session
     where v$lock.type = 'TX'
       and v$lock.sid = v$session.sid
       and v$session.USERNAME = 'GWM';

    select xidusn,xidslot,xidsqn from v$transaction;

    select (select username from v$session where sid = a.sid) blocker,
           a.sid,
           ' is blocking ',
           (select username from v$session where sid = b.sid) blockee,
           b.sid
      from v$lock a, v$lock b
     where a.BLOCK = 1
       and b.REQUEST > 0
       and a.ID1 = b.ID1
       and a.ID2 = b.ID2;
    --提交原来的事务(sid=145),并重新运行锁出现,请求行就消失了。

    create语句的两个物理参数
    initrans:这个结构的初始预分配大小。默认为2
    maxtrans:这个结构可以扩缩的最大大小。默认为255.但是在oracle 10g中这个设置已经废弃了,在oracle10g中只要块上的空间足够,
    即使设置了maxtrans,oracle也会不受约束地扩大事务表。若是在oracle9i或之前的版本,一旦达到maxtrans值,事务表就不会再扩大了。
    如:
    create table t1 (x int) maxtrans 2;
    insert into t1 select rownum from all_users;
    select distinct dbms_rowid.rowid_block_number(rowid) from t;

    --在该会话中执行如下语句
    update t set x=1 where x=1;
    --在另一个会话中执行如下语句
    update t set x=2 where x=2;
    --在又另一个会话中执行如下语句
    update t set x=3 where x=3;
    发现都可以顺利更新,因为oracle10g尽管在设置时将maxtrans设为2,但是maxtrans始终为255。如果是在之前的版本,就会发现到第三个会话的时候
    就会出现锁定状态

    2、TM(DML Enqueue)锁
    该锁用于确保在修改表的内容时,表的结构不会改变。
    如果已经有一个TM锁,另一用户试图在这个表上执行DDL,就会得到如下错误。
    drop table t2
    error at line 1:
    ora-00054:resource busy and acquire with nowait specified

    create table t1 (x int);
    create table t2 (x int);

    insert into t1 values(1);
    insert into t2 values(1);

    select (select username from v$session where sid = v$lock.sid) username,
           sid,
           id1,
           id2,
           lmode,
           request,
           block,
           v$lock.type
      from v$lock
     where sid = (select sid from v$mystat where rownum = 1);

    select object_name,object_id from user_objects where object_name in ('T1','T2');
    --尽管每个事务只能得到一个TX锁,但是TM锁则不同,修改了多少个对象,就能得到多少个TM锁。而且TM锁的ID1列就是DML锁定对象的对象ID

    3、DDL锁
    三个类型
    1)排他DDL锁
    alter table t1 add new_column date;
    在执行这个语句时,表t1不能被别人修改。在此期间,可以使用select查询这个表,但是大多数其他操作都不允许执行,包括所有DDL语句。在oracle中,
    现在有些DDL操作没有DDL锁也可以发生。如:
    create index t_idx on t1(x) online;
    online 关键字会改变具体建立索引的方法。oracle并不是加一个排他DDL锁来防止数据修改,而只会试图得到表上的一个低级(mode2)TM锁。这会有效
    防止其他DDL发生,同时还允许DML正常允许。

    2)共享DDL锁
    :在创建 存储的编译对象时,会对依赖的对象加这种共享DDL锁。如:
    create view myview as select * from emp,dept where emp.deptno=dept.deptno;
    表emp和dept上都会加共享DDL锁,而create view命令仍在处理。可以这些表的内容,但是不能修改它们的结构。

    3)可中断解析锁
    :你的回话解析一条语句时,对于该语句引用的每一个对象都会加一个解析锁。
    dba_ddl_locks(如果该视图没有安装,可以通过以sys的身份执行D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN该目录的catblock.sql脚本)

    select session_id sid,owner,name,type,mode_held held,mode_requested request from dba_ddl_locks;
    为看到一个实际的可中断的解析锁,下面先创建并运行存储过程p:
    create or replace procedure p as begin null;end;
    exec p
    执行p过程后,过程p会出现在dba_ddl_locks视图中。即有这个过程的一个解析锁:
    select session_id sid,owner,name,type,mode_held held,mode_requested request from dba_ddl_locks;
    对该存储过程进行编译后在执行查询视图:编译后再查询该视图发现该p过程不在这个视图中了。--必须在sqlplus中执行,在plsql执行得不到这个结果。
    alter  procedure p compile;
    select session_id sid,owner,name,type,mode_held held,mode_requested request from dba_ddl_locks;

    闩(latch)
    :也是一种锁
    latch“自旋”的问题:即当latch不是立即可用的,我们就得等待,在一台多cpu机器上,我们的会话就会自旋(spin),即在循环中反复地尝试来得到latch
    。出现自旋的原因:上下文切换的开销很大,所以进程不能立即得到latch,我们就会一直待在cpu上,并立即再次尝试,而不是先睡眠,放弃cpu,
    等到必须调度回cpu时才再次尝试。
    latch的开销很大,对于不使用绑定变量与绑定变量的语句相比,消耗的时间,cpu都要多得多。

    手动锁定和用户自定义锁
    手动锁定:
    通过select...for update语句来手动锁定数据
    或者通过使用lock table语句手动锁定。这个语句很少使用,因为锁的粒度大,它只是锁定表,而不是锁定行。

    创建自己的锁:
    通过dbms_lock包。如可以利用该包,在打开、写入和关闭文件之前,可以采用排他模式请求一个锁,一次只能有一个人向这个文件写消息。这样所有人都会排队。

  • 相关阅读:
    为什么要对url进行encode
    活在当下
    Linux Shell 文本处理工具
    Servlet、Servlet容器等内容讲解
    Java编程中的一些常见问题汇总
    创建文件目录
    ubuntu
    iptables
    mysqldump导入导出
    pt-table-sync
  • 原文地址:https://www.cnblogs.com/lanzi/p/1931960.html
Copyright © 2011-2022 走看看