Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 504|回复: 0

Oracle系列-锁表与解锁解决方案(基础版)

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-16 11:55:57 | 显示全部楼层 |阅读模式

    【Oracle锁表查询和解锁解决方案】

    一、了解原因(借鉴整理)

    数据库操作语句的分类

    DDL:数据库模式定义语言,关键字:create
    DML:数据操纵语言,关键字:Insert、delete、update
    DCL:数据库控制语言 ,关键字:grant、remove
    DQL:数据库查询语言,关键字:select
    oracle表在什么情况下会被锁住

    DML锁又可以分为,行锁、表锁、死锁

    行锁:当事务执行数据库插入、更新、删除操作时,该事务自动获得操作表中操作行的排它锁。

    表级锁:当事务获得行锁后,此事务也将自动获得该行的表锁(共享锁),以防止其它事务进行DDL语句影响记录行的更新。事务也可以在进行过程中获得共享锁或排它锁,只有当事务显示使用
    LOCK TABLE语句显示的定义一个排它锁时,事务才会获得表上的排它锁,也可使用LOCK TABLE显示的定义一个表级的共享锁(LOCK TABLE具体用法请参考相关文档)。

    死锁:当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就出现死锁。
    如事务1在表A行记录#3中有一排它锁,并等待事务2在表A中记录#4中排它锁的释放,而事务2在表A记录行#4中有一排它锁,并等待事务1在表A中记录#3中排它锁的释放,事务1与事务2彼此等
    待,因此就造成了死锁。死锁一般是因拙劣的事务设计而产生。
    死锁只能使用SQL下:alter system kill session “sid,serial#”;或者使用相关操作系统kill进程的命令,如UNIX下kill -9 sid,或者使用其它工具杀掉死锁进程。

    DDL锁又可以分为:排它DDL锁、共享DDL锁、分析锁

    排它DDL锁:创建、修改、删除一个数据库对象的DDL语句获得操作对象的 排它锁。如使用alter table语句时,为了维护数据的完成性、一致性、合法性,该事务获得一排它DDL锁。

    共享DDL锁:需在数据库对象之间建立相互依赖关系的DDL语句通常需共享获得DDL锁。
    如创建一个包,该包中的过程与函数引用了不同的数据库表,当编译此包时,该事务就获得了引用表的共享DDL锁。

    分析锁:ORACLE使用共享池存储分析与优化过的SQL语句及PL/SQL程序,使运行相同语句的应用速度更快。一个在共享池中缓存的对象获得它所引用数据库对象的分析锁。分析锁是一种独特的
    DDL锁类型,ORACLE使用它追踪共享池对象及它所引用数据库对象之间的依赖关系。当一个事务修改或删除了共享池持有分析锁的数据库对象时,ORACLE使共享池中的对象作废,下次在引用这
    条SQL/PLSQL语句时,ORACLE重新分析编译此语句。

    Oracle锁表查询和解锁

    就由解决以下问题来说明:

    在进行批量对DML操作时程序竟然中断了,不再往下执行、查询一下某张表被锁住了,因此不再往下执行了。

    第一步:通过管理员权限用户查询被锁表信息

    如果怀疑表被锁了,或者事务未被正常关闭,在Oracle数据库中我们可以通过以下语句进行查询获取相关信息:

    select t2.username,
    t2.sid,
    t2.serial#,
    t3.object_name,
    t2.OSUSER,
    t2.MACHINE,
    t2.PROGRAM,
    t2.LOGON_TIME,
    t2.COMMAND,
    t2.LOCKWAIT,
    t2.SADDR,
    t2.PADDR,
    t2.TADDR,
    t2.SQL_ADDRESS,
    t1.LOCKED_MODE
    from v$locked_object t1, v$session t2, dba_objects t3
    where t1.session_id = t2.sid
    and t1.object_id = t3.object_id
    order by t2.logon_time;
    大家发现,上面这条SQL语句用到了Oracle的两个视图和一个表,分别是v$locked_object、v$session、dba_objects:
    v$locked_object 视图中记录了所有session中的所有被锁定的对象信息。
    v$session 视图记录了所有session的相关信息。
    dba_objects 为oracle用户对象及系统对象的集合,通过关联这张表能够获取被锁定对象的详细信息。

    eg:现在我通过scott用户执行DML语句(eg:select * from emp for update;或者update scott.emp set sal = '2000' where empno='7788'; )之后一直不进行提交,然后通过system用户
    执行上面的查询oracle中被锁表的sql语句,就会找到如下记录:
    这里写图片描述

    说明:
    username:oracle用户名
    sid:进程号
    serial#:序列号
    object_name:表名
    osuser:操作系统用户名
    machine:机器名
    program:操作工具
    logon_time:登陆时间
    lockwait:表示当前这张表是否正在等待其他用户解锁这张表
    locked_mode:锁表模式(下面详细说明)

    注意:这时候如果通过system用户执行select * from scott.emp for update;语句就无法成功执行。

    第二步:通过拥有管理员权限的用户解除数据库中被锁住的表(SID,SERIAL)

    通过第一步查出来的信息找到被锁的表之后执行如下语句解锁该表:

    alter system kill session 'sid,seial#';
    1
    注意:sid和seial#就是第一步中查询出来的进程号和序列号。

    eg:解除第一步中表的锁

    alter system kill session '10,15';
    1
    现在通过system再次执行DML语句(eg:select * from scott.emp for update;或update scott.emp set sal = '2000' where empno='7788';)就可以了。

    锁的模式

    v$locked_object中的LOCKED_MODE字段表示锁的模式,oracle中锁的模式有如下几种:
    0:none
    1:null 空
    2:Row-S 行共享(RS):共享表锁,sub share
    3:Row-X 行独占(RX):用于行的修改,sub exclusive
    4:Share 共享锁(S):阻止其他DML操作,share
    5:S/Row-X 共享行独占(SRX):阻止其他事务操作,share/sub exclusive
    6:exclusive 独占(X):独立访问使用,exclusive

    数字越大锁级别越高, 影响的操作越多。

    1级锁有:Select,有时会在v$locked_object出现。
    2级锁有:Select for update,Lock For Update,Lock Row Share
    select for update当对话使用for update子串打开一个游标时,所有返回集中的数据行都将处于行级(Row-X)独占式锁定,其他对象只能查询这些数据行,不能进行update、delete或select
    for update操作。
    3级锁有:Insert, Update, Delete, Lock Row Exclusive
    没有commit之前插入同样的一条记录会没有反应, 因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。
    4级锁有:Create Index, Lock Share
    locked_mode为2,3,4不影响DML(insert,delete,update,select)操作, 但DDL(alter,drop等)操作会提示ora-00054错误。
    00054, 00000, “resource busy and acquire with NOWAIT specified”
    // *Cause: Resource interested is busy.
    // *Action: Retry if necessary.
    5级锁有:Lock Share Row Exclusive
    具体来讲有主外键约束时update / delete … ; 可能会产生4,5的锁。
    6级锁有:Alter table, Drop table, Drop Index, Truncate table, Lock Exclusive

    还有一条比较实用的sql:

    --查某session 正在执行的sql语句,从而可以快速定位到哪些操作或者代码导致事务一直进行没有结束等.
    SELECT /*+ ORDERED */
    sql_text
    FROM v$sqltext a
    WHERE (a.hash_value, a.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 b
    WHERE b.sid = '67') /* 此处67 为SID*/
    ORDER BY piece ASC;

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-9 12:36 , Processed in 0.076038 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表