oracle中锁的问题--在OS一级杀掉oracle杀不掉的进程--查杀锁表进程

前两天同事又碰到oracle连接n慢的问题,由于这个现象时有时无,于是我检查了下是不是表或者其他对象有被锁住,或者是否有死锁。对象资源被锁是一个经常要碰到的急需解决的问题。

 

在Oracle里,当前的锁的信息存储在动态性能视图v$lock和v$locked_object中。先来看下它们定义:

 

Oracle官方文档及简单翻译 (oracle官方可下载资源网址在我的收藏里有列出):

V$LOCK V$LOCKED_OBJECTV$LOCKED_OBJECT lists all locks acquired by every transaction on the system. It shows which sessions are holding DML locks (that is, TM-type enqueues) on what objects and in what mode.

V$LOCK lists the locks currently held by the Oracle Database and outstanding requests for a lock or latch.

视图V$LOCK列出了当前被Oracle数据库持有的所有的锁以及未完成的锁和栓锁请求。

Column Datatype Description
ADDR RAW(4 | 8) Address of lock state object/内存中被锁的对象的地址
KADDR RAW(4 | 8) Address of lock/内存中锁地址
SID NUMBER Identifier for session holding or acquiring the lock/持有或申请锁的会话标识号
TYPE VARCHAR2(2) Type of user or system lock/系统锁或者用户锁类型

The locks on the user types are obtained by user applications. Any process that is blocking others is likely to be holding one of these locks. The user type locks are:

TM - DML enqueue/表级锁或DML锁

TX - Transaction enqueue/行级锁或事务锁

UL - User supplied/用户锁

The locks on the system types are held for extremely short periods of time. The system type locks are listed in Table 8-1 .

 

ID1 NUMBER

Lock identifier #1 (depends on type)

锁的第1标识号

如果锁的类型是TM,该值表示将要被锁定的对象的标识号;

如果锁的类型是TX,该值表示撤销段号码的十进制值

ID2 NUMBER

Lock identifier #2 (depends on type)

锁的第2标识号。

如果锁的类型是TM,该值为0;

如果锁的类型是TX,该值表示交换次数

LMODE NUMBER

Lock mode in which the session holds the lock:

会话保持的锁的模式

  • 0 - none

  • 1 - null (NULL) 空

  • 2 - row-S (SS) 行共用(RS):共用表锁,sub share

  • 3 - row-X (SX)  行独占(RX):用于行的修改,sub exclusive

  • 4 - share (S) 共用锁(S):阻止其他DML操作,share

  • 5 - S/Row-X (SSX) 共用行独占(SRX):阻止其他事务操作,share/sub exclusive

  • 6 - exclusive (X) 独占(X):独立访问使用,exclusive

锁的级别越高影响的操作越多。
REQUEST NUMBER

Lock mode in which the process requests the lock:

会话申请的锁的模式。与LMODE中的模式相同

  • 0 - none

  • 1 - null (NULL)

  • 2 - row-S (SS)

  • 3 - row-X (SX)

  • 4 - share (S)

  • 5 - S/Row-X (SSX)

  • 6 - exclusive (X)

CTIME NUMBER

Time since current mode was granted

以秒为单位的,获得当前锁(或转换成当前锁的模式)以来的时间

BLOCK NUMBER

A value of either 0 or 1, depending on whether or not the lock in question is the blocker.

当前锁是否阻塞另一个锁。0=不阻塞;1=阻塞

 

视图V$LOCKED_OBJECT列出系统中每个事务获得的所有锁。它列出了那些以具体哪些模式对具体哪些对象持有TM锁的会话。

Column Datatype Description
XIDUSN NUMBER Undo segment number/撤销段号码
XIDSLOT NUMBER Slot number/被锁定的对象在撤销段中的位置
XIDSQN NUMBER Sequence number/序列号
OBJECT_ID NUMBER Object ID being locked/被锁定的对象的标识号
SESSION_ID NUMBER Session ID/ 会话的标识号
ORACLE_USERNAME VARCHAR2(30) Oracle user name/Oracle用户名
OS_USER_NAME VARCHAR2(30) OS user name/操作系统用户名
PROCESS VARCHAR2(12) OS process ID/操作系统进程标识号
LOCKED_MODE NUMBER Lock mode/

对象被锁定的模式。

0=None;1=Null;2=Row-S (SS);3=Row-X (SX);

4=Share;5=S/Row-X (SSX);6=Exclusive

 

查找有关锁/死锁的更多我们需要的信息有时还需要通过表all_objects或者视图v$session,它们就不再一一讲解,请到oracle官方文档 查询。

 

查询有关锁的信息:

 

查询一:

 select a.os_user_name,
         a.oracle_username,
          a.object_id,
          c.object_name,
       c.object_type
    from v$locked_object a, dba_objects c
    where a.object_id=c.object_id;

 

查询二:

 

select s.PROCESS,
       s.SID,
       s.SERIAL#,
       b.object_name,
       b.subobject_name,
       a.LOCKED_MODE,
       s.OSUSER,
       s.LOGON_TIME,
       s.MACHINE,
       s.PROGRAM,
       s.SQL_ADDRESS,
       s.SQL_HASH_VALUE            
  from v$locked_object a, dba_objects b, v$session s
where a.OBJECT_ID = b.object_id
   and a.SESSION_ID = s.SID

 

找到锁/死锁就好办了。找到相应需要解开的锁可以通过完成该事务或者杀死会话解锁。

 

杀锁进程可以用以下命令:

alter system kill session ' '查出的SID,查出的SERIAL#'。(这个必须要用查询二来获得相关Session信息)

 

杀oracle会话进程有时会失效,需要根据SPID到系统中杀相应的oracle进程。另外要注意的是, 我看到网上有外国的学者说, 当直接连接数据库时, 直接用OS命令 $kill process_num 或者 $kill -9 process_num杀系统进程来终止用户连接也不能完全解决问题, 因为一个用户进程可能产生一个以上的锁,杀oracle进程不能彻底解决锁的问题。

 

Reference:

http://www.lslnet.com/linux/edosc/42/linux-42294950.htm

 

 

/////////////////

 

一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长时间不释放,有时实在没办法,只好重启数据库。现在提供一种方法解决这种问题,那就是在ORACLE中杀不掉的,在OS一级再杀。 

1.下面的语句用来查询哪些对象被锁: 

select object_name,machine,s.sid,s.serial# 
from v$locked_object l,dba_objects o ,v$session s 
where l.object_id = o.object_id and l.session_id=s.sid; 

2.下面的语句用来杀死一个进程: 
alter system kill session '24,111'; (其中24,111分别是上面查询出的sid,serial#) 

【注】以上两步,可以通过Oracle的管理控制台来执行。 

3.如果利用上面的命令杀死一个进程后,进程状态被置为"killed",但是锁定的资源很长时间没有被释放,那么可以在os一级再杀死相应的进程(线程),首先执行下面的语句获得进程(线程)号: 
select spid, osuser, s.program 
from v$session s,v$process p 
where s.paddr=p.addr and s.sid=24 (24是上面的sid) 

4.在OS上杀死这个进程(线程): 
1)在unix上,用root身份执行命令: 
#kill -9 12345(即第3步查询出的spid) 
2)在windows(unix也适用)用orakill杀死线程,orakill是oracle提供的一个可执行命令,语法为: 
orakill sid thread 
其中: 
sid:表示要杀死的进程属于的实例名 
thread:是要杀掉的线程号,即第3步查询出的spid。 
例:c:>orakill orcl 12345

 

 

/////////////

 

查看当前用户的sid和serial#:

select sid, serial#, status from v$session where audsid=userenv('sessionid');

 

查看当前用户的spid:

select spid from v$process p, v$session s where s.audsid=userenv('sessionid') and s.paddr=p.addr;

select spid from v$process p join v$session s on p.addr=s.paddr and s.audsid=userenv('sessionid');

 

查看当前用户的trace file路径:

select p.value || '/' || t.instance || '_ora_' || ltrim(to_char(p.spid,'fm99999')) || '.trc'

    from v$process p, v$session s, v$parameter p, v$thread t

    where p.addr = s.paddr and s.audsid = userenv('sessionid') and p.name = 'user_dump_dest';

 

已知spid,查看当前正在执行或最近一次执行的语句:

select /*+ ordered */ sql_text from v$sqltext sql

    where (sql.hash_value, sql.address) in (

        select decode(sql_hash_value, 0, prev_hash_value, sql_hash_value), decode(sql_hash_value, 0, prev_sql_addr, sql_address)

        from v$session s where s.paddr = (select addr from v$process p where p.spid = to_number('&pid')))

    order by piece asc;

 

查看锁和等待:

col user_name format a10

col owner format a10

col object_name format a15

col sid format 999999

col serial# format 999999

col spid format a6

select /*+ rule */ lpad(' ', decode(l.xidusn, 0, 3, 0)) || l.oracle_username user_name,

    o.owner, o.object_name, o.object_type, s.sid, s.serial#, p.spid

    from v$locked_object l, dba_objects o, v$session s, v$process p

    where l.object_id = o.object_id and l.session_id = s.sid and s.paddr = p.addr

    order by o.object_id, xidusn desc;

 

///////////

 

查看锁表进程SQL语句1: 
select sess.sid, 
    sess.serial#, 
    lo.oracle_username, 
    lo.os_user_name, 
    ao.object_name, 
    lo.locked_mode 
    from v$locked_object lo, 
    dba_objects ao, 
    v$session sess 
where ao.object_id = lo.object_id and lo.session_id = sess.sid; 

查看锁表进程SQL语句2: 
select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID; 

杀掉锁表进程: 
如有记录则表示有lock,记录下SID和serial# ,将记录的ID替换下面的738,1429,即可解除LOCK 
alter system kill session '738,1429';


转自:http://blog.csdn.net/thunder09/article/details/5418500

发布了5 篇原创文章 · 获赞 10 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章