首页 > 数据库 >oracle锁

oracle锁

时间:2023-09-12 19:34:55浏览次数:52  
标签:object 会话 session sid oracle id select

ORACLE TM锁与TX锁联系

理论部分:

1. DML 锁

DML 锁(也称为数据锁)保证多个用户同时访问的数据的完整性。例如,DML 锁可防止两个客户购买在线书商提供的图书的最后一本。DML 锁可防止同时发生冲突的 DML 或 DDL 操作。对用户的数据操纵, Oracle 可以自动为操纵的数据进行加锁,但也可以人为的实施加锁。DML 锁可由一个用户进程以显式的方式加锁,也可通过某些 SQL 语句隐含方式实现。

1.1. TX锁

行锁,也称为 TX 锁,是单行表上的锁。当事务执行数据库插入、更新、删除操作时,该事务自动获得操作表中操作行的排它锁。事务发起第一个修改时会得到TX 锁,而且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。行锁主要用作排队机制,以防止两个事务修改同一行。数据库始终以独占模式锁定已修改的行,以便其他事务在持有锁的事务提交或回滚之前无法修改该行。

1.2. TM锁

TM 锁用于确保在修改表的内容时,表的结构不会改变,例如防止在 DML 语句执行期间相关的表被移除。当用户对表执行 DDL 或 DML 操作时,将获取一个此表的表级锁。当事务获得行锁后,此事务也将自动获得该行的表锁(共享锁),以防止其它事务进行 DDL 语句影响记录行的更新。事务也可以在进行过程中获得共享锁或排它锁,只有当事务显示使用 LOCK TABLE 语句显示的定义一个排它锁时,事务才会获得表上的排它锁,也可使用 LOCK TABLE 显示的定义一个表级的共享锁。TM 锁包括了 SS、 SX、 S、 X 等多种模式,在数据库中用 0-6 来表示。不同的 SQL 操作产生不同类型的 TM 锁

 

mode

名称

解释

对应的sql操作

0

none

 

 

1

null

Select

2

SS

共享行表锁

Select/lock for update,lock row share

3

SX

共享行级排他表锁

Insert,update,delete,lock row share

4

S

共享表锁

Create index,lock share

5

SSX

共享行级排他表锁

lock share row exclusive

6

X

排他表锁

Alter/truncate table,drop index/table

 

1.3. Enq:tx row lock contention

enq是一种保护共享资源的锁定机制,一个排队机制排它机制。从一个事务的第一次改变直到rollback or commit 结束这个事务,TX等待mode是6,当一个session 在一个表的行级锁定时另一个会话总是等待,一般发生在一些用户插入或更新,而另一个用户同样也在插入或更新这同一批数据时发生。这种类型的等待通常就是eventenq:TX-rowlockcontention.解决方法是让第一个会话commit or rollback 结束这个事务。如果tx等待事件中mode如果是4,这种一般发生在同时更新一个数据块上的数据,但不一定是同一条记录,这就是热块。对于这种enq:TX - row lock等待事件,如果mode=6,那么唯一的解决方法就是kill 会话或者调整业务逻辑。

2. 锁相关的视图

2.1 V$lock视图

ADDR 锁状态对象的地址

KADDR 锁地址

SID         会话保持或获取锁的标识符

TYPE        用户或系统锁定的类型

ID1         锁定标识符

ID2     锁定标识符

LMODE 会话保持锁定的锁定模式:

REQUEST 进程请求锁定的锁定模式:

CTIME     自授予当前模式以来的时间

BLOCK 指示有问题的锁定是否阻止其他进程。可能的值为:

0- 锁未阻止任何其他进程

1- 锁正在阻止其他进程

2- 锁未阻止本地节点上任何阻塞的进程,但它可能会也可能不会阻塞远程节点上的进程。

2.2 Locked_object视图

XIDUSN                 撤消段编号

XIDSLOT                 插槽编号

XIDSQN                 序列号

OBJECT_ID             对象ID

SESSION_ID             会话ID

ORACLE_USERNAME           oracle用户名

OS_USER_NAME         操作系统用户名

PROCESS                 操作系统进程 ID

LOCKED_MODE             锁定模式

ID1对应视图V$TRANSACTION中的XIDUSN字段(Undo segment number:事务对应的撤销段序列号)和XIDSLOT字段(Slot number:事务对应的槽位号)。其中ID1的高16位为XIDUSN,低16位为XIDSLOT。

ID2对应视图V$TRANSACTION中的XIDSQN字段(Sequence number:事务对应的序列号)。

2.3 DBA_LOCK视图

DBA_LOCK列出数据库中持有的所有锁或闩锁,以及所有未完成的锁或闩锁请求。

SESSION_ID    会话持有或获取锁

LOCK_TYPE    锁类型

MODE HELD    锁定模式

MODE REQUESTED  请求锁定模式

LOCK_ID1        特定于类型的锁标识符,第 1 部分

LOCK_ID2        特定于类型的锁标识符,第 2 部分

LAST_CONVERT    最后一次转换

BLOCKING_OTHERS  锁当前是否阻止了其他锁

实验部分:

模拟出enq:tx row lock等待事件:

创建一个表并插入两行数据:

SQL> Create table pipi(id varchar(10),age varchar(10));
Table created
SQL> insert into pipi values('pipi','3');
1 row created.
SQL> insert into pipi values('zhegu','3');
1 row created.

提交更新结果以及查询更新结果:

SQL> commit;
Commit complete.
SQL> select * from pipi;
ID         AGE
---------- ----------
pipi       3
zhegu      3

 会话一:

执行update pipi set age=’12’;

SQL> update pipi set age='12';
2 rows updated.

会话二:

执行update pipi set age=’9’ where id=’pipi’;

发现会话2卡住

开启会话3:

首先在v$lock视图中相应的sid、锁类型和锁等级

SQL>  select sid,type,lmode,ctime from gv$lock where type='TM';
       SID TY      LMODE      CTIME
---------- -- ---------- ----------
        19 TM          3        400
      1353 TM          3        522
SQL> select sid,type,lmode,ctime from gv$lock where type='TX';
       SID TY      LMODE      CTIME
---------- -- ---------- ----------
        19 TX          0        425
      1353 TX          6        547

查询对应的等待事件:

SQL> select sid, seq#, state, seconds_in_wait,event
  2  FROM v$session_wait WHERE event='enq: TX - row lock contention';
       SID       SEQ# STATE               SECONDS_IN_WAIT
---------- ---------- ------------------- ---------------
EVENT
----------------------------------------------------------------
        19         24 WAITING                         894
enq: TX - row lock contention

由此enq:TX -row lock contention等待事件模拟成功

查询是哪个会话id阻塞了另外一个会话:

第一种方法:在Gv$session 里查找final_blocking_session参数:

SQL> select inst_id, final_blocking_session, sid, serial#, final_blocking_session_status
from gv$session where blocking_session is not null order by blocking_session;  
   INST_ID BLOCKING_SESSION        SID    SERIAL# BLOCKING_SE
---------- ---------------- ---------- ---------- -----------
         1             1353         19      56206 VALID

 blocking_session_status有几个值:其中valid代表有一个会话阻塞该会话,noholder代表没有会话阻塞该会话,no in wait代表会话不在等待中,unkonwn代表未知

由查询的内容可知:1353阻塞了19会话

第二种方法:在gv$lock和gv$locked_object查找:

先查找出哪些会话阻塞了其他会话:select sid,block from gv$lock where block='1';

SQL> select sid,block from gv$lock where block='1';
 
       SID      BLOCK
---------- ----------
      1353          1

查询被阻塞会话:select object_id,session_id from v$locked_object where object_id in (select object_id from v$locked_object where session_id=('&sid'));

SQL> select object_id,session_id from v$locked_object where object_id in (select object_id from v$locked_object where session_id=('&sid'));
Enter value for sid: 1353
old   1: select object_id,session_id from v$locked_object where object_id in (select object_id from v$locked_object where session_id=('&sid'))
new   1: select object_id,session_id from v$locked_object where object_id in (select object_id from v$locked_object where session_id=('1353'))
 OBJECT_ID SESSION_ID
---------- ----------
114363         19
114363       1353

 确定19会话被1353阻塞。

第三种方法:dba_waiters和dba_blockers查找(仅仅试用与阻塞和被阻塞在同一节点)

查找阻塞会话的会话:

SQL> select * from dba_blockers;
HOLDING_SESSION     CON_ID
--------------- ----------
           1353          1
SQL> select waiting_session,holding_session from dba_waiters;
WAITING_SESSION HOLDING_SESSION
--------------- ---------------
             19            1353

确定了阻塞会话通过sid找到对应的sql_id:

select inst_id,

sid, serial#, wait_class, sql_id from   gv$session

where blocking_session IS NOT NULL and sid=('&sid');

通过sql_id查找出相应的sql语句;确保不会误杀会话

杀死会话:alter system kill session ‘sid,serial#,@inst_id’;

其中sid是整个会话生命周期的一个唯一标识符,sid+serial#是整个实例生命周期的唯一标识符(避免误杀情况出现),inst_id代表当前节点号(避免误杀情况出现)。

SQL> alter system kill session '19,56206,@1';

System altered.

被阻塞会话执行commit;并查询更新后的结果:

补充:若想查询一个被阻塞会话的阻塞源头:可采用gv$session视图中的final_blocking相关参数

相应的sql语句:

select inst_id, final_blocking_session, sid, serial#, final_blocking_session_status from gv$session where blocking_session is not null order by blocking_session;

 

标签:object,会话,session,sid,oracle,id,select
From: https://blog.51cto.com/u_13482808/7447540

相关文章

  • Oracle 引发No space left on device+扩容Inode
    Oracle引发Nospaceleftondevice+扩容Inode背景很久没遇到数据库存储和文件系统相关的问题,碰到了就复习一下。现象是:某个小应用跑在很老的服务器上【准备淘汰废弃待定中】,突然应用报错,检查发现是数据库查询插入都异常了【自建oracle数据库】,这时候登上数据库服务器,查看一下......
  • 如何使用Oracle Enterprise Manager Database Express连接到PDB数据库
    1.问题重复弹出登录框,无法登陆关闭登录框,显示invalidcontainername2.解决方法参考链接为PDB启动EMExpress要为PDB启动EMExpress,请确保PDB以读/写模式打开,然后尝试本主题中描述的以下方法之一(按所示顺序):连接到包含PDB的CDB的CDB$ROOT容器,并发出以下SQL......
  • 通过 DBCA 创建 Oracle Database 21c 的进度停滞在 36%
    1.问题安装过程中一直卡在36%检查dbca日志文件位于H:\app\trmbh\cfgtoollogs\dbca\ORCL\trace.log_2023-09-12_12-04-20PM卡在executingdatapatch这一步上了2.解决方法感谢大佬!转载自:https://ahmedfattah.com/2021/10/30/oracle-database-21c-creation-via-dbca-han......
  • ORACLE Enterprise Manager Database Express(OEM-express)配置端口和启动方法
    1.问题之前一直进不去ORACLEEnterpriseManagerDatabaseExpress,显示的是localhost拒绝了访问,经过查阅知道是没有配置相应端口。2.解决方法转载自:https://blog.csdn.net/wshjx0001/article/details/1224660151.首先查看监听状态,如果监听没有启动需要先启动监听2.在SQLpl......
  • oracle安装成功后,更改字符集
    看了网上的文章,乱码有以下几种可能 1.操作系统的字符集 2.oracleserver的字符集 3.客户端的字符集 1.查看oracle的字符集   1.selectuserenv('language')fromdual2.在Ubuntu中.bashrc中加入下边的话:   exportNLS_LANG=AMERICAN_AMERICA.ZHS16GBK(改掉操作系......
  • Oracle over(partition by) 用法
    语法与说明selectAAA,序号函数over(partitionbyBBBgroupbyCCC)fromtable;select后面跟什么字段随便。序号函数有多种,类似row_number()等。partitionby后面跟的字段实际是分组字段,与groupby后面跟的字段类似。再之后的order字段,就是分组后排序。序号函数说明......
  • Oracle 查询当前用户下所有索引(Index)并拼接创建脚本
    原文地址:https://blog.csdn.net/zy_workjob/article/details/82011825 Oracle查询当前用户下所有索引(Index,PK)并拼接创建脚本【不包含FUNCTION-BASED基于函数的索引】SELECTT.TABLE_NAME,--表名T.INDEX_NAME,--索引名I.UNIQUENESS,--是否非空I.INDEX_......
  • oracle sql*plus常用命令
    文章转载自:https://www.cnblogs.com/csschn/p/4864653.html一、sys用户和system用户Oracle安装会自动的生成sys用户和system用户(1)、sys用户是超级用户,具有最高权限,具有sysdba角色,有createdatabase的权限,该用户默认的密码是change_on_install(2)、system用户是管理操作员,权......
  • 数据库数据恢复-Oracle数据库误执行truncate table的数据恢复案例
    Oracle数据库故障&分析:北京某单位Oracle11gR2数据库误执行truncate table CM_CHECK_ITEM_HIS,表数据丢失,查询该表时报错。数据库备份无法使用,表数据无法查询。Oracle数据库Truncate数据的机理:执行Truncate命令后,ORACLE数据库会在数据字典和Segment Header中更新表的Data O......
  • oracle 去重函数(逗号分割后去重,行转列)
    createorreplacefunctionaaa_distinct(avarchar2)returnvarchar2asresultsvarchar2(2000):='';begin selectlistagg(CONTRACTNO_listagg,',')withingroup(orderbyCONTRACTNO_listagg)intoresultsfrom(selectdistinctsubs......