2、检测并解决冲突
我们先执行下面的语句获得当前session的SID号,然后执行DML语句:
SQL> select sid from v$mystat where rownum=1;
SID
----------
159
SQL> update employees set last_name=last_name||'a'
where department_id=60;
6 rows updated.
结果显示出,该事务更新了6条记录。然后我们来检查该事务的状态:
SQL> select xidusn,xidslot,xidsqn,status from v$transaction;
xIDUSN    xIDSLOT     xIDSQN    STATUS
---------- ---------- ---------- ----------------
6           36       5839   ACTIVE
我们看到该事务使用了6号回滚段,槽号为36号。然后我们观察v$lock视图:
SQL> select sid,type,id1,id2,decode(lmode,0,'None',1,'Null',
2,'Row share',
2          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',
6,'Exclusive') lock_mode,
3          decode(request,0,'None',1,'Null',2,'Row share',
4          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',
6,'Exclusive') request_ mode,block
5  from v$lock
6  where sid=159;
SID   TYPE     ID1      ID2     LOCK_MODE       REQUEST_MODE   BLOCK
---- ----- -------- ----------  -------------- -------------  ------
159   TM         53777           0   Row Exclusive      None       0
159   TX        393252       5839   Exclusive        None          0
从输出结果中我们可以看到两个级别的锁:TX和TM。对于TX来说,Oracle只有一种模式,也就是排他模式。同时我们应该会注意到,该事务更新了6条记录, 但是只有一个行级锁,并不是会产生6个行级锁。事实上,TX锁也叫做事务锁(transaction,其中的X表示事务)。也就是说,一个事务只会产生一个TX锁。 而对于TM锁定来说,其锁定模式为行级排他锁。
对于TM锁来说,ID1表示被锁定的对象的对象ID,ID2始终为0。如下所示:
SQL> select object_name from dba_objects where object_id=53777;
OBJECT_NAME
-------------------------------
EMPLOYEES
对于TX锁来说,ID1表示事务使用的回滚段编号以及在事务表中对应的记录编号,ID2表示该记录编号被重用的次数(wrap)。使用下面的SQL语句将上面的 ID1(393252)转换为直观的数字:
SQL> select trunc(393252/power(2,16)) as undo_blk#,
2         bitand(393252,to_number('ffff','xxxx')) + 0
as slot#
3  from dual;
UNDO_BLK#      SLOT#
---------- ----------
6           36
可以看到,该值与v$transaction中记录的值是一样的。
我们再启动一个session,获得SID号以后,执行下面的DML语句:
SQL> select sid from v$mystat where rownum=1;
SID
----------
131
SQL> update employees set last_name=last_name||'b' where
department_id=60;
131号session所发出的DML语句被阻塞了,无法执行下去。我们执行下面的SQL语句:
SQL> select sid,type,id1,id2,decode(lmode,0,'None',1,'Null',2,'
Row share',
2          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',
6,'Exclusive') lock_mode,
3          decode(request,0,'None',1,'Null',2,'Row share',
4          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',
6,'Exclusive') request_ mode,block
5  from v$lock
6  where sid in(159,131)
7  order by sid;
SID   TYPE   ID1       ID2          LOCK_MODE            REQUEST
_MODE    BLOCK
----  ----- -------- ----------  --------------     -------------
-------
131    TM       53777            0    Row Exclusive     None         0
131    TX      393252        5839     None               Exclusive   0
159    TX      393252        5839     Exclusive         None         1
159    TM       53777            0     Row Exclusive    None         0
可以看到,131号session在TX锁的请求模式(request_mode列)上为排他锁,因为131号session要更新记录,就必须获得被更新记录上的排他锁。但是由于 这些记录正在被159号session锁定,没能获得行级锁,因此其锁定模式(lock_mode)为None。有趣的是,这时131号session的事务信息(ID1与ID2的值)与 159号session的事务信息是完全一样的,因为131号session的事务由于无法获得锁定,因此还没能开始。131号session在TM锁定上,已经获得了行级排他锁 。因为159号session在表上添加的RX锁定,并不会阻止其他session在相同表上添加RX锁。
我们可以再次启动另一个session,并执行下面的DML语句:
SQL> select sid from v$mystat where rownum=1;
SID
----------
135
SQL> update employees set last_name=last_name||'c' where
department_id=60;
这时,我们查询v$enqueue_lock来获得锁定队列中的session信息。
SQL> select sid,type,decode(request,0,'None',1,'Null',2,'Row share',
2         3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') request_mode
3  from v$enqueue_lock
4  where sid in(131,135);
SID            TYPE    REQUEST_MODE
----------   ----    -------------------
131            TX       Exclusive
135            TX       Exclusive
可以看到,131号session先进入队列,而135号session后进入队列。我们还可以使用下面的SQL语句将session之间的阻塞关系显示得更加清楚:
SQL> select a.sid blocker_sid,a.serial#,a.username as blocker_username,
2         b.type,decode(b.lmode,0,'None',1,'Null',2,'Row share',
3          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') lock_mode,
4         b.ctime as time_held,c.sid as waiter_sid,
5         decode(c.request,0,'None',1,'Null',2,'Row share',
6          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') request_mode,
7         c.ctime time_waited
8  from   v$lock b, v$enqueue_lock c, v$session a
9  where  a.sid     = b.sid
10  and    b.id1     = c.id1(+)
11  and    b.id2     = c.id2(+)
12  and    c.type(+) = 'TX'
13  and    b.type    = 'TX'
14  and    b.block   = 1
15  order by time_held, time_waited;
BLOCKER_SID    SERIAL#   BLOCKER_USERNAME     TY       LOCK_MODE
-----------    --------  ----------------     -----   ----------
159                5    HR                      TX       Exclusive
159                5    HR                      TX       Exclusive
TIME_HELD WAITER_SID   REQUEST_MODE     TIME_WAITED
---------   ----------   -----------      -----------
5488           135    Exclusive                    5
5488           131    Exclusive                 2770
从输出结果中可以很明显地看出,159号session阻塞了135号和131号session。要解决该锁定冲突,我们只需要让159号session提交事务即可,提交以后再次 查询v$lock:
SQL> select a.sid blocker_sid,a.serial#,a.username as blocker_username,
2         b.type,decode(b.lmode,0,'None',1,'Null',2,'Row share',
3          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') lock_mode,
4         b.ctime as time_held,c.sid as waiter_sid,
5         decode(c.request,0,'None',1,'Null',2,'Row share',
6          3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',
6,'Exclusive') request_ mode,
7         c.ctime time_waited
8  from   v$lock b, v$enqueue_lock c, v$session a
9  where  a.sid     = b.sid
10  and    b.id1     = c.id1(+)
11  and    b.id2     = c.id2(+)
12  and    c.type(+) = 'TX'
13  and    b.type    = 'TX'
14  and    b.block   = 1
15  order by time_held, time_waited;
BLOCKER_SID    SERIAL#   BLOCKER_USERNAME     TY       LOCK_MODE
-----------    --------  ----------------     -----   ----------
131                6    HR                      TX      Exclusive
TIME_HELD WAITER_SID   REQUEST_MODE     TIME_WAITED
---------   ----------   -----------      -----------
357            135   Exclusive                  215
由于在Oracle中使用队列来锁定,在队列中的session按照先进先出的原则,先进入队列的session先获得锁定。因此,当159号session释放锁定以后,131号 session会获得锁定,而135号session则被131号session阻塞。
如果159号session无法提交,则我们可以发出下面的语句直接删除159号session:
SQL> alter system kill session '150,6';
其中,150为session的SID号,而6为session的SERIAL#号。当删除159号session以后,该session所获得的锁定就会被pmon进程释放。
当我们更新某个表的记录,于是在表级别上添加RX模式的TM锁定。这时如果其他的用户要删除该表或修改该表结构时,则需要在表上添加X模式的TM锁定。由 于RX模式与X模式不兼容,则报错。如下所示:
SQL> drop table employees;
drop table employees
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
从前面我们已经看到,一个事务不管更新多少条记录,都只能获得一个TX锁定。但是一个事务可以获得多个TM锁定。我们来看下面的例子:
SQL> select sid from v$mystat where rownum=1;
SID
----------
150
SQL> update employees set last_name=last_name||'a' where
department_id=60;
6 rows updated.
SQL> update departments set department_name='unknow' where
department_id=10;
1 row updated.
SQL> update locations set city='unknown' where location_id=1100;
1 row updated.
在同一个事务中,我们总共更新了3个表。然后检查v$lock视图:
SQL> select sid,type,id1,id2,decode(lmode,0,'None',1,'Null',2,
'Row share',
2         3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') lock_mode,
3         decode(request,0,'None',1,'Null',2,'Row share',
4         3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,
'Exclusive') request_mode,block
5  from v$lock
6  where sid=150;
SID   TYPE       ID1           ID2     LOCK_MODE       REQUEST_MODE    BLOCK
----  ----- -------- ----------  --------------     -------------   -------
150    TM        53777           0    Row Exclusive      None           0
150    TM        53772           0    Row Exclusive      None           0
150    TM        53767           0    Row Exclusive      None           0
150    TX       262185        5932    Exclusive          None           0
可以看到,我们获得了1个TX锁定及3个TM锁定。或者说,TX锁定与事务个数相同,而TM锁定则与被更新的表的个数相同。
在数据库系统中,我们同时可以获得的TX锁定的总个数由初始化参数transactions决定,而可以获得的TM锁定的个数则由初始化参数dml_locks决定。如下所 示:
SQL> select name,value from v$parameter where name in('transactions',
'dml_locks');
NAME                   VALUE
----------------    -------
dml_locks                748
transactions            187
默认情况下,同时可以启动187个事务,也就是获得187个TX锁定,以及获得748个TM锁定。也就是说,平均每个事务更新4个表(748/187=4)。我们还可以查 看v$resource_limit视图来了解这两个资源的使用情况:
SQL> select resource_name as "R_N",current_utilization as "C_U",max_
utilization as "M_U",
2  initial_allocation as "I_U" from v$resource_limit where resource
_name in('transactions ','dml_locks');
R_N                C_U          M_U          I_U
---------------  ---------- ---------- ----------
dml_locks          4            55          748
transactions       2            7          187
从结果中可以看到当前所使用的资源个数(C_U字段)、曾经达到过的同时被使用的资源的最大个数(M_U字段)、能够分配的资源的最大个数(I_U字段)。 这两个初始化参数修改以后,都必须重启实例使之生效。如果将初始化参数transactions设置为0,则重启以后,会发现初始化参数dml_locks也被自动设置 为0。但是我们查询视图v$resource_limit:
SQL> select resource_name as "R_N",current_utilization as "C_U",
max_utilization as "M_U",
2  initial_allocation as "I_U" from v$resource_limit where
resource_name in('transactions ','dml_locks');
R_N                C_U          M_U          I_U
---------------  ---------- ---------- ----------
dml_locks           0            0            0
transactions        0            5          187
输出结果说明,尽管我们将transactions设置为0,但是仍然可以发出事务操作语句,同时能够发出的最大事务个数仍然为默认的187个事务。而dml_locks的 资源个数则确实为0了,但这并不是说明不能对表添加表级锁,而只是说明不能进行大部分的DDL操作了。比如我们这时发出删除employees表的命令,如下所 示:
SQL> drop table employees;
drop table employees
*
ERROR at line 1:
ORA-00062: DML full-table lock cannot be acquired; DML_LOCKS is 0

转载于:https://blog.51cto.com/19880614/1187024

oracle教程之解决DML事务锁定的冲突(二)相关推荐

  1. oracle教程之DML事务锁定的机制

    锁定能够保证当某个用户正在更新表里的一行数据时,其他用户不能同时更新相同的数据行,而且也不能删除或修改被更新的表. 锁定分为两种级别:行级别(TX锁)和表级别(TM锁). 1.行级锁(TX锁) 假设某 ...

  2. oracle 创建记录锁,oracle教程之创建自己的锁定

    对于锁定来说,尽管其概念比较复杂,但是Oracle将这些复杂性都屏蔽在Oracle的内核中.Oracle会自动完成锁的管理,通常并不需要我们对锁定进行很多 的管理工作.不仅如此,Oracle还是提供了 ...

  3. 【Oracle 11g中 ORA-28000 账号被锁定的解决办法】

    Oracle 11g中 ORA-28000 账号被锁定的解决办法 ORA-28000账号被锁定的原因 如何修改 登录SYS用户 修改默认的登录限制次数 解锁被锁定的用户->解决 ORA-2800 ...

  4. oracle operation_type,案例:Oracle报错performing DML/DDL operation over object in bin解决办法

    天萃荷净 运维DBA在巡检时发现alert日志文件中出现Oracle报错performing DML/DDL operation over object in bin,分析原因为回收站中的对象执行了d ...

  5. Oracle VM VirtualBox创建虚拟机教程并解决连接网路问题和连接Xshell

    Oracle VM VirtualBox创建虚拟机教程并解决连接网路问题和连接Xshell 一.安装Virtual Box 1.什么是Virtual Box: VirtualBox 是一款开源虚拟机软 ...

  6. oracle教程课件,Oracle教程三PPT课件

    <Oracle教程三PPT课件>由会员分享,可在线阅读,更多相关<Oracle教程三PPT课件(29页珍藏版)>请在人人文库网上搜索. 1.第三章 锁和分区表,.,2,回顾,S ...

  7. 第1章 Oracle教程

    第一章 Oracle教程 简单查询语句(重点) 简单查询指的是将数据表中的全部内容查询出来进行显示,语法如下: SELECT * | 列名称 别名,列名称 别名 FROM 表名称 别名 ; 范例:查询 ...

  8. 事务,Oracle,MySQL及Spring事务隔离级别

    一.什么是事务:  事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. 二.事务特性(4种):  原子性 (atomicity):强调事务的不可分割: 一致性 (consi ...

  9. 解决MySQL事务未提交导致死锁报错 避免死锁的方法

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/xuheng8600/article/d ...

最新文章

  1. 【转】WSS3.0开发--你还在为写CAML痛苦吗?
  2. middleware generic错误处理机制
  3. 链路聚合-CISCO
  4. Reporting Services 的伸缩性和性能表现规划(转载)
  5. 中兴计算机专业,中兴计算机专业面试题.pdf
  6. 订阅号、服务号与企业号区别
  7. java构造反射和函数_反射类的构造函数和方法
  8. boost mysql_玩转MySQL 8.0源码编译
  9. python生成序列_python 之 生成序列号
  10. 2021-03-04
  11. spacedesk安卓_【图吧小白教程】安卓平板改数位板
  12. 机器视觉该怎么样系统学习
  13. 双目测量空间中两点距离
  14. html上下两个箭头符号怎么打出来,双横向箭头符号怎么打,双横向箭头符号怎么打...
  15. Python基础之Scrapy简介
  16. RabbitMQ学习(二)-Rabbit的使用
  17. influxDB快速入门实战教程
  18. 计算机调剂到mba,这8种考生不能调剂!MBA/MPAcc等考研生注意
  19. 蔡氏混沌电路matlab程序,蔡氏混沌电路简介——Chuaapos;s-Circut.pptx-全文可读
  20. 系统工程理论与实践投稿经验_【系统工程理论与实践杂志】投稿经验与期刊点评_审稿、版面费用_退稿_要求与流程_影响因子_级别_发行周期_见刊时间_极作期刊...

热门文章

  1. 4年猎洞赚百万美金:谈谈我的入门和成功经验
  2. PPP 守护进程 RCE 漏洞已存在17年,可控制几乎所有的 Linux 系统
  3. 一键伪装成 Windows 10:Kali Linux 2019.4 版本推出 “Undercover” 模式
  4. Bootstrap Table插件 页面跳转后再回来保存搜索的值
  5. [Luogu1462]通往奥格瑞玛的道路
  6. 让网络更轻盈——网络功能虚拟化技术的现状和未来(中兴通讯)
  7. paas-openshift
  8. Java ADF Template程序不能连接ArcGIS Server问题
  9. [Java] 蓝桥杯BASIC-25 基础练习 回形取数
  10. python打乱数据集_在Keras中利用np.random.shuffle()打乱数据集实例