• 查锁的方法


    查锁的方法:

    有用的SQL... PAGEREF _Toc117741710 h 1 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310030000000

    1:检查系统中锁的简单脚本:... PAGEREF _Toc117741711 h 1 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310031000000

    2:获取数据库锁的信息(用户IDOBJECTSQL... PAGEREF _Toc117741712 h 1 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310032000000

    3:产生等待锁的用户报告... PAGEREF _Toc117741713 h 2 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310033000000

    4:显示持有锁的信息:... PAGEREF _Toc117741714 h 2 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310034000000

    SQL脚本... PAGEREF _Toc117741715 h 3 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310035000000

    1. 诊断系统中的锁... PAGEREF _Toc117741716 h 3 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310036000000

    2. 解除锁... PAGEREF _Toc117741717 h 4 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310037000000

    一个加速查询锁表和等待锁的方法... PAGEREF _Toc117741718 h 5 08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310037003700340031003700310038000000

    有用的SQL

    1:检查系统中锁的简单脚本:

    Select s.username s.sid l.type l.id1 l.id2 l.lmode l.request p.spid PID
    From v$lock l
    v$session s v$process p
    Where s.sid = l.sid And p.addr = s.paddr And s.username is not null
    Order By id1
    s.sidrequest;

    获取用户SIDPID,锁的种类,锁的类型等信息

    2:获取数据库锁的信息(用户IDOBJECTSQL

    REM *****************************************************************

    REM TITLE : Generic Script which displays SQL Text REM SID
    and Object name of the locks currently REM being held in the database.
    REM MODULE : lock_held.sql
    Set pagesize 60
    Set linesize 132
    select s.username username
    a.sid sid a.owner||'.'||a.object object s.lockwait t.sql_text SQL
    from v$sqltext t
    v$session s v$access a
    where t.address = s.sql_address and t.hash_value = s.sql_hash_value
    and s.sid = a.sid and a.owner != 'SYS'
    and upper(substr(a.object
    12)) != 'V$' ;
    REM REM End of "Lock Monitoring Script" REM

    3:产生等待锁的用户报告

    SELECT sn.usernamem.sid m.type DECODE(m.lmode 0 'None' 1 'Null' 2 'Row Share'
    3
    'Row Excl.' 4 'Share' 5 'S/Row Excl.' 6 'Exclusive' lmode
    ltrim(to_char(lmode
    '990'))) lmode
    DECODE(m.request
    0 'None' 1 'Null' 2 'Row Share' 3 'Row Excl.' 4 'Share'
    5
    'S/Row Excl.' 6 'Exclusive' request ltrim(to_char(m.request'990'))) request
    m.id1
    m.id2
    FROM v$session sn
    v$lock m |
    WHERE (sn.sid = m.sid AND m.request != 0)
    OR ( sn.sid = m.sid AND m.request = 0 AND lmode != 4 AND (id1
    id2) IN (SELECT s.id1 s.id2
    FROM v$lock s
    WHERE request != 0 AND s.id1 = m.id1 AND s.id2 = m.id2) )
    ORDER BY id1
    id2 m.request;

    4:显示持有锁的信息:

    select nvl(S.USERNAME'Internal') username nvl(S.TERMINAL'None') terminal L.SID||''||S.SERIAL# Kill U1.NAME||'.'||substr(T1.NAME120) tab
    decode(L.LMODE
    1'No Lock' 2'Row Share' 3'Row Exclusive' 4'Share'
    5
    'Share Row Exclusive' 6'Exclusive'null) lmode
    decode(L.REQUEST
    1'No Lock' 2'Row Share' 3'Row Exclusive' 4'Share'
    5
    'Share Row Exclusive' 6'Exclusive'null) request
    from V$LOCK L
    V$SESSION S SYS.USER$ U1 SYS.OBJ$ T1
    where L.SID = S.SID and T1.OBJ# = decode(L.ID2
    0L.ID1L.ID2) and U1.USER# = T1.OWNER# and S.TYPE != 'BACKGROUND'
    order by 1
    25

    SQL脚本

    1. 诊断系统中的锁

    为了找出系统中那些用户锁住资源以及那些用户在等待相应的资源,可使用以下语句(其中的/*+ NO_MERGE(..) */千万不可省略, 否则会很慢)

    -- looklock.sql

    -- use the NO_MERGE hints can speed up the query

    select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Wait' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
    from v$session a, v$lock b, v$sqltext c
    where a.username is not null
    and a.lockwait = b.kaddr
    and c.hash_value =a.sql_hash_value
    union
    select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Lock' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
    from v$session a, v$lock b, v$sqltext c
    where b.id1 in
    (select /*+ NO_MERGE(d) NO_MERGE(e) */ distinct e.id1
    from v$session d, v$lock e
    where d.lockwait = e.kaddr)
    and a.username is not null
    and a.sid = b.sid
    and b.request=0
    and c.hash_value =a.sql_hash_value;

    执行后的结果如下所示:

    Stat USERNAME MACHINE SID SERIAL# Seconds ID1

    ---- ------------------------------ ---------------- --------- --------- --------- ---------

    SQL

    ----------------------------------------------------------------

    Lock CIQUSR CIQDULMACER 12 966 245 131089
    select * from c_trade_mode for update
    Wait CIQUSR CIQDULMACER 10 735 111 131089
    update c_trade_mode set x_name = 'zzz' where x_code='5'
    Wait CIQUSR CIQDULMACER 15 106 1094 131089
    select * from c_trade_mode for update

    其中:

    Status有两种状态,LOCK表明该进程锁住了某个资源,WAIT表示该进程正在等待某个资源。

    Username, Machine分别为ORACLE用户名及机器名

    SIDSERIAL#可用于随后的解锁操作

    Seconds表示该进程最后一次进行操作至当前的时间()

    ID1, 锁标识。某个LOCK状态的ID1与某个WAIT状态的ID1相同,可说明锁的正是另一个进程等待的。

    SQL: 锁住资源的SQL语句

    2. 解除锁

    诊断出锁的状态后,若发现该阻塞其它用户进程的进程是正常操作中,则可通知该用户对其进行提交,从而达到释放锁资源的目的;若为非正常操作,即,其状态为 "inactive",且其Seconds已为较多长时间,则可执行以下语句将该进程进行清除,系统会自动对其进行回滚,从而释放锁住的资源。

    alter system kill session 'sid, serial#';

    例如: 对于上例中显示的结果, 可用以下语句清除锁住资源的进程:

    alter system kill session '12, 966';

    关于你所说:在网络断掉(通过拔掉网线)或非正常终止进程(通过task manager强行关闭sql*plus)时,oracle在有限的时间内(我只观查了5-10分)内,oracle未能对该进程作任何处理。

    这个处理与TCP协议有关,因为SQL NET在使用TCP/IP协议进行网络连接时是一种短连接,ORACLE连接异常终止时,因为是异常终止,终止信号并没有通过网络通知server端,因此只有下次server有结果从服务器端返回需与client通信时,server才会发现此client已经端掉。因此出现你前面所提ORACLE处理异常终止进程延时情况.

    查锁语句:查询产生锁的用户锁sql

    select a.username username, a.sid sid, a.serial# serial,b.id1 id1, c.sql_text sqltext
    from v$session a, v$lock b, v$sqltext c
    where b.id1 in
      
    (select distinct e.id1
      
    from v$session d, v$lock e
      
    where d.lockwait = e.kaddr)
      
    and a.sid = b.sid
      
    and c.hash_value = a.sql_hash_value
      
    and b.request = 0;

    一个加速查询锁表和等待锁的方法

    --- 这些锁定中有"只读锁""排它锁""共享排它锁"等多种类型,而且每种类型又有"行级锁"(一次锁住一条记录),"页级锁"(一次锁住一页,即数据库中存储记录的最小可分配单元),"表级锁"(锁住整个表)

    --- 若为"行级排它锁",则除被锁住的该行外,该表中其它行均可被其它的用户进行修改(update)或删除(delete)操作,若为"表级排它锁",则所有其它用户只能对该表进行查询(select)操作,而无法对其中的任何记录进行修改或删除。当程序对所做的修改进行提交(commit)或回滚后 (rollback)后,锁住的资源便会得到释放,从而允许其它用户进行操作。

    oracle 8.0.x 中执行"获取正在等待锁资源的用户名"的查询语句十分缓慢

    select a.username, a.sid, a.serial#, b.id1
    from v$session a, v$lock b
    where a.lockwait = b.kaddr

    查找阻塞其它用户的用户进程也十分缓慢

    select a.username, a.sid, a.serial#, b.id1
    from v$session a, v$lock b
    where b.id1 in
    (select distinct e.id1
    from v$session d, v$lock e
    where d.lockwait = e.kaddr)
    and a.sid = b.sid
    and b.request = 0

    一个解决办法。即通过将问题发生时的 v$lockv$session视图中的相关记录保存于自己建立的表中,再对该表进行查询,则速度大大提高,可以迅速发现问题。经实际使用,效果非常好。在接到用户反映后,几秒钟即可查出由于锁住资源而影响其它用户的进程,并进行相应的处理。

    首先,以 dba 身份(不一定为system)登录入数据库中,创建三个基本表:my_sessionmy_lock, my_sqltext,并在将会进行查询的列上建立相应的索引。语句如下:

    rem v$session 视图中取出关心的字段,创建 my_session ,并在查询要用到的字段上创建索引,以加快查询速度

    drop table my_session;
    create table my_session
    as
    select a.username, a.sid, a.serial#,
    a.lockwait, a.machine,a.status,
    a.last_call_et,a.sql_hash_value,a.program
    from v$session a
    where 1=2 ;

    create unique index my_session_u1 on my_session(sid);
    create index my_session_n2 on my_session(lockwait);
    create index my_session_n3 on my_session(sql_hash_value);
    ---- rem
    v$lock 视图中取出字段,创建 my_lock 表,并在查询要用到的字段上创建索引,以加快查询速度

    drop table my_lock;
    create table my_lock
    as
    select id1, kaddr, sid, request,type
    from v$lock
    where 1=2;

    create index my_lock_n1 on my_lock(sid);
    create index my_lock_n2 on my_lock(kaddr);

    ---- rem v$sqltext 视图中取出字段,创建 my_sqltext 表,并在查询要用到的字段上创建索引,以加快查询速度
    drop table my_sqltext;
    create table my_sqltext
    as
    select hash_value , sql_text
    from v$sqltext
    where 1=2;
    create index my_sqltext_n1 on my_sqltext ( hash_value);

    -- 然后,创建一个 sql 脚本文件,以便需要时可从 sql*plus 中直接调用。其中,首先用 truncate table 表名命令将表中的记录删除。之所以用 truncate 命令,而不是用delete 命令,是因为delete 命令执行时,将会产生重演记录,速度较慢,而且索引所占的空间并未真正释放,若反复做 insertdelete,则索引所占的空间会不断增长,查询速度也会变慢。而 truncate命令不产生重演记录,速度执行较delete快,而且索引空间被相应地释放出来。删除记录后,再将三个视图中的相关记录插入自己创建的三个表中。最后,对其进行查询,由于有索引,同时由于在插入时条件过滤后,记录数相对来说较少,因而查询速度很快,马上可以看到其结果。

    ---- 此时,若发现该阻塞其它用户进程的进程是正常操作中,则可通知该用户对其进行提交,从而达到释放锁资源的目的;若为未正常操作,即,其状态为 "inactive",且其last_call_et已为较多长时间,则可执行以下语句将该进程进行清除,系统会自动对其进行回滚,从而释放锁住的资源。

    alter system kill session ''sid, serial#''

    -- sql 脚本如下:
    set echo off
    set feedback off
    prompt ''
    删除旧记录.....''
    truncate table my_session;
    truncate table my_lock;
    truncate table my_sqltext;

    prompt ''获取数据.....'
    insert into my_session
    select a.username, a.sid, a.serial#,
    a.lockwait, a.machine,a.status,
    a.last_call_et,a.sql_hash_value,a.program
    from v$session a
    where nvl(a.username,''null'')< >''null”;

    insert into my_lock
    select id1, kaddr, sid, request,type
    from v$lock;

    insert into my_sqltext
    select hash_value , sql_text
    from v$sqltext s, my_session m
    where s.hash_value=m.sql_hash_value;

    column username format a10
    column machine format a15
    column last_call_et format 99999 heading "seconds"
    column sid format 9999
    prompt "
    正在等待别人的用户"

    select a.sid, a.serial#,
    a.machine,a.last_call_et, a.username, b.id1
    from my_session a, my_lock b
    where a.lockwait = b.kaddr;

    prompt "被等待的用户"
    select a.sid, a.serial# ,a.machine ,a.last_call_et ,a.username
    ,b.type ,a.status,b.id1
    from my_session a, my_lock b
    where b.id1 in
    (select distinct e.id1
    from my_session d, my_lock e
    where d.lockwait = e.kaddr)
    and a.sid = b.sid
    and b.request=0;

    prompt "查出其 sql "
    select a.username, a.sid, a.serial#,
    b.id1, b.type, c.sql_text
    from my_session a, my_lock b, my_sqltext c
    where b.id1 in
    (select distinct e.id1
    from my_session d, my_lock e
    where d.lockwait = e.kaddr)
    and a.sid = b.sid
    and b.request=0
    and c.hash_value =a.sql_hash_value;

  • 相关阅读:
    hibernate中HQL多对多的查询
    Georgia Tech- 新的篇章
    吴军《智能时代》读书笔记
    P5项目完成记录
    Codewar python训练题全记录——持续更新
    优达学城纳米学位P5项目知识点总结——github使用
    优达学城数据分析师纳米学位——P5项目知识点整理贝叶斯规则
    优达学城数据分析师纳米学位——P5项目知识点整理机器学习基本术语
    P3-SQL 学习笔记
    HTML+CSS 学习笔记
  • 原文地址:https://www.cnblogs.com/liangqihui/p/297865.html
Copyright © 2020-2023  润新知