Lock(二)解决Lock问题

本文介绍通过Toad、EM及SQL语句来处理数据库产生的锁。在这之前需要对v$lockv$session这两个数据字典有一定的了解。

(一)使用Toad处理锁

(1)使用Toad的session browser查看锁情况

这里对每一个字段进行解释:

栏位名称 说明
SID session ID,每一个session都会产生一个sid,用于标识会话
User 产生锁的数据库用户
Lock Type
锁的类型,常见的有:

--DML锁

--Transaction锁(事物锁)等

Mode Held session保持锁的模式:
--none
--null(NULL)
--row-S(SS,行级共享锁。其它session只能查询这些数据行。SQL操作有select for update、lock for update、lock row share)
--row-X(SX,行级排它锁。在提交前不允许做DML操作。SQL操作有insert、update、delete、lock row share)
--share(S,共享锁。SQL操作有create index,lock share)

--S/Row-X(SSX,共享行级排它锁。SQL操作有lock share row exclusive)
--exclusive(X,排它锁。SQL操作有alter table、drop table、drop index、truncate table、lock exclusive等DDL操作)

Owner 被锁定的对象的属主
Object Type 被锁定的对象类型
Object Name 被锁定的对象名称
Blocking 该session是否正在阻塞其他session对资源进行访问。YES代表阻塞
Session Blocked 该会话是否正处于被阻塞的状态,打勾代表该session正在被其他session阻塞
OS User 建立该session的用户的OS名称
Machine Name 建立该session的用户的Machine名称

(2)使用Toad解锁

(二)使用SQL命令处理锁

(1)查看锁信息

select
  se.machine,
  se.sid,
  se.serial#,
  se.seconds_in_wait,
  se.paddr,
  lo.block
from
  v$lock lo,
  v$session se
where
 lo.sid = se.sid
and
 lo.block > 0;    --bloc>0代表这个会话阻塞了其他会话

(2)查看哪个数据库对象被锁

select
  lo.sid,
  do.owner,
  do.object_name
from
  v$lock lo,
  dba_objects do
where
  lo.id1 = do.object_id
and
  lo.sid = 23;    --这里23是例子,我们需要根据上一步得到的sid来查看具体对象

(3)Kill Session

alter system kill session ‘sid,serial#‘;    --sid,serial从第1步中得到

(4)如果利用上面的命令杀死一个进程后,进程状态被置为"killed",但是锁定的资源很长时间没有被释放,那么可以在os一级再杀死相应的进程(线程),首先执行下面的语句获得进程(线程)号:

select
  pr.spid,  --我们要的
  se.osuser,
  se.program
from
  v$session se,
  v$process pr
where
  se.paddr=pr.addr
and
  se.sid=24    --sid从第1步得到

(5)在OS级别Kill Process

(5.1) 在unix上,用root身份执行命令:

su - root
#kill -9 spid    --即第步查询出的spid

(5.2)在windows(unix也适用)用orakill杀死线程,orakill是oracle提供的一个可执行命令,语法为:

orakill sid thread

其中:
sid:表示要杀死的进程属于的实例名 ,与上面的session id不同
thread:是要杀掉的线程号,即第4步查询出的spid

例:c:>orakill orcl 12345

(三)模拟锁的产生及处理

(1)对scott.emp表进行行更新,但是不提交

SQL> select * from scott.emp;

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
 7369 SMITH      CLERK      7902 1980/12/17     800.00               20
 7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30
  …    …           …

14 rows selected

SQL> update scott.emp set job = ‘SALESMAN‘ where empno = 7369;

1 row updated

(2)使用Toad查看锁情况,已经可以看到锁的存在

(3)查看EM,从EM的top activity并不能看到锁的情况

(4)查看V$lock。V$lock记录了当前数据库中存在的全部锁,锁是Oracle的一种正常的机制,但从这个视图并不能看出什么。对于用户而言,最关心的是TM和TX锁,结合上面Toad的结果,我们可以看到session id = 46的会话已经持续了454s。

SQL> select * from v$lock;

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
...              ...
000000008D45B1C0 000000008D45B218         53 AE          100          0          4          0        436          0
00007F2A9960F420 00007F2A9960F480         46 TM        73201          0          3          0        454          0
000000008C105C90 000000008C105D08         46 TX       458781       1379          6          0        454          0

对于TM锁(表级锁),ID1代表的是被锁定的object_id,ID2为0,通过dba_object可以查看到正在被锁的对象的名称。

SQL> select owner,object_name,object_id,object_type from dba_objects where object_id = 73201;

OWNER  OBJECT_NAME   OBJECT_ID OBJECT_TYPE
------ ------------ ---------- ------------
SCOTT  EMP               73201 TABLE

(5)再来查看v$session视图,SECOND_IN_WAIT字段代表会话处于等待的时间。

SQL> select se.SADDR,se.SID,se.SERIAL#,se.PADDR,se.USERNAME,se.MACHINE,se.SECONDS_IN_WAIT  from v$session se;

SADDR                   SID    SERIAL# PADDR            USERNAME                       MACHINE                     SECONDS_IN_WAIT
---------------- ---------- ---------- ---------------- ------------------------------ --------------------------- ---------------
000000008DF74F68         46         13 000000008DC9F4D0 LIJIAMAN                       WORKGROUP\DESKTOP-TKAPD8E   1585
000000008DF720F8         47        235 000000008DCA0510 DBSNMP                         localhost.localdomain       11
...                     ...        ...

(6)在同一个session中执行delete操作,在新开的session中执行update操作。通过Toad,我们可以看到,在sid=46的session上,存在2个DML锁,值得一提的是,在我们对表emp进行操作时,由于其外键在dept表上,也将dept表锁住了。三个DML锁都是SX锁,即行级排它锁,46上还有一个x锁,即排它锁。

SQL> delete from scott.emp where emp.empno = 7369;
SQL> update scott.emp set emp.sal = sal + 200 where emp.empno = 7369 ;

结果如图:

由于执行了delete操作,将dept表也锁了起来

(7)此时,再去观察EM,可看到大量的Application阻塞。并且可以看到这个阻塞是有sid=54的session引起的

通过SQL ID查看具体执行的SQL语句

(8)此时查看v$lock。从红色部分可以看到, session46与session54对object id = 73201的对象产生了表级锁竞争,并且目前session46正在占用该表,导致该session阻塞了session54。

SQL> select * from v$lock;

ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
00007F2A9960C378 00007F2A9960C3D8         54 TM        73201          0          3          0       1510          0
00007F2A9960C378 00007F2A9960C3D8         46 TM        73201          0          3          0       3707          0
00007F2A9960C378 00007F2A9960C3D8         46 TM        73199          0          3          0       1798          0
000000008C105C90 000000008C105D08         46 TX       458781       1379          6          0       3707          1

(9)Kill Session

SQL> alter system kill session ‘46,13‘;

System altered

至此锁解除。

时间: 2024-08-11 13:04:30

Lock(二)解决Lock问题的相关文章

[MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))

对于稍微有点经验的.NET开发人员来说,倘若被问及如何保持线程同步,我想很多人都能说好好几种.在众多的线程同步的可选方式中,加锁无疑是最为常用的.如果仅仅是基于方法级别的线程同步,使用System.Runtime.CompilerServices.MethodImplAttribute无疑是最为简洁的一种方式.MethodImplAttribute可以用于instance method,也可以用于static method.当在某个方法上标注了MethodImplAttribute,并指定Met

mysql 有报错  ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists

sh-4.1# /etc/init.d/mysqld status ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists sh-4.1# /etc/init.d/mysqld start Starting MySQL. ERROR! The server quit without updating PID file (/data1/mysql/mysql.pid). sh-4.1# rm mysql

java.util.concurrent.locks.Lock类的lock和lockInterruptibly方法的区别

什么是可中断的锁获取呢?就是:线程在等待获取锁的过程中,是否能够响应中断,以便在被中断的时候能够解除阻 塞状态,而不是傻傻地一直在等待.java对象的内置锁(synchronized)就是一种不可中断的锁,也就是说如果一个线 程在等待获取某个对象的内置锁,就算是该线程被其他线程中断,该线程仍然继续等待内置锁,而不是解除阻塞状 态,也不会抛出InterruptedException.Lock类的lock()类似synchronized,是不可中断的,在等待获取锁的过程中, 不响应中断请求:lock

lock(this)、lock(class) 、lock(object)

1. lock(this) 锁定是当前对象的实例 2.lock(class) 3.lock(object) 任意引用对象,只要是同一个引用地址都可以同步 4.lock(this) 与 lcok(class)使用 5.lock(值类型对象)   会发生自动装箱,object=new object(值类型对象),导致[锁不住],无法实现同步,故无法使用值类型对象 6.使用lock (String.Intern(str.ToString()))来同步 原文地址:https://www.cnblogs.

iOS "The sandbox is not in sync with the Podfile.lock"解决方式

更新Cocoapod之后出现故障: diff: /../Podfile.lock: No such file or directory diff: Manifest.lock: No such file or directory error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.` 解决方式: 关闭如今的工作空间,删掉曾经

mysql metadata lock(二)

上一篇<mysql metadata lock(一)>介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问.本文将更详细的介绍MDL,主要侧重介绍MDL的原理和实现.一般而言,商业数据库系统实现锁,一般将锁划分为读锁(共享锁)和写锁(排它锁),为了进一步提高并发性,还会加入意向共享锁和意向排它锁.但是偏偏mysql的MDL搞地比较复杂,但目的也是为了提高并发度.MDL包含有9种类型,详细参考表1.主要其实也是两大类,只是对共享锁做了进一步细分.

关于Git无法提交 index.lock的解决办法(学)

今天提交代码时,在一次提交,莫名其妙没成功后,再次用git commit -a命令时,出现以下错误,无论是用git还是TortoiseGit都会出现以下这个问题.. $ git commit -a fatal: Unable to create 'e:/git/Android/XXXXXX/.git/index.lock': File exists. If no other git process is currently running, this probably means a git p

MySQL5.7报错[ERROR] Unix socket lock file is empty /tmp/mysql.sock.lock的解决方法

发现MySQL服务器因系统磁盘写满导致服务停了,清理磁盘后启动服务时无法正常启动,查看localhost.err日志发现如下报错: [ERROR] Unix socket lock file is empty /tmp/mysql.sock.lock 解决: 查看该文件发现确实是空文件,删除该文件后再启动服务已经可以正常启动.参考链接 https://blog.csdn.net/qq_36183569/article/details/83022519 总结: mysql.sock.lock是可读

MySQL Waiting for table metadata lock的解决方法

最近需要在某一个表中新增字段,使用Sequel Pro 或者Navicat工具都会出现程序没有反应,使用 show processlist 查看,满屏都是 Waiting for table metadata lock 状态的连接,第一反应当然是 kill 掉这些链接,但是假如太多怎么办?遂在找寻其他办法. 在网上查询得知MySQL在进行一些alter table等DDL操作时,如果该表上有未提交的事务则会出现 Waiting for table metadata lock ,而一旦出现meta