189 8069 5689

Oracle学习之性能优化(十)锁-创新互联

 锁(lock)是用于防止在访问相同的资源(包括用户对象、系统对象、内存、Oralce数据字典中的共享数据结构,最常见的是数据库表Table对象)时 ,事务之间的有害性 交互(存、取)的一种机制。

成都创新互联公司IDC提供业务:成都多线服务器托管,成都服务器租用,成都多线服务器托管,重庆服务器租用等四川省内主机托管与主机租用业务;数据中心含:双线机房,BGP机房,电信机房,移动机房,联通机房。

 不同类型的锁,代表了当前用户是允许还是阻止其它用户对相同资源的同时存取,从而确保不破坏系统数据的完整性、一致性和并行性。

 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

锁的分类

  • DML锁:SELECT、INSERT、UPDATE、DELETE、MERGE操作

  • DDL锁:CREATE和ALTER语句操作

  • 内部锁和闩:Oracle使用这些锁来包含内部数据结构,例如:Oracle查询生成的执行计划,执行计划会保存在库缓存中,当使用这个执行计划时,会对其加一个闩(latch)

DML锁

 用于确保一次只能一个人修改某行数据。而且你正常处理这个表时,别人不能删除这个表。

  1. TX锁,事务发起第一个修改时,会得到一个TX锁(事务锁),而且会一直持有这个事务,直到事务结束(COMMIT或者ROLLBACK)。事务中修改或者select for update的每一行都会指向该事务的TX锁。

  2. TM锁,用于确保在修改表内容时,表的结构不被改变。

下面举例说明

登录到scott用户,并确定session id

SQL> grant select any dictionary to scott; Grant succeeded. SQL> conn scott/tiger SQL> select sid from v$mystat where rownum=1;        SID ---------- 37 SQL>

另开启一个会话,监控锁的使用情况

SQL> set linesize 200 SQL> select * from v$lock where sid=37; ADDR  KADDR  SID TY        ID1   ID2    LMODE    REQUEST  CTIME     BLOCK ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 0000000090D8FC88 0000000090D8FCE0   37 AE        100     0        4   0    481 0 SQL>

会话1执行更新操作

SQL> update emp set ename=initcap(ename); 14 rows updated.

会话2查看结果

SQL> / ADDR  KADDR  SID TY        ID1   ID2    LMODE    REQUEST  CTIME     BLOCK ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 0000000090D8FC88 0000000090D8FCE0   37 AE        100     0        4   0    944 0 00007FF9EEDA4AB0 00007FF9EEDA4B10   37 TM      87108     0        3   0      3 0 000000008F673658 000000008F6736D0   37 TX     131074   908        6   0      3 0

多了一个事务锁,一个TM锁。

会话1中再执行另一个表的更新操作

SQL> update dept set dname=initcap(dname); 4 rows updated.

会话2查看结果

SQL> / ADDR  KADDR  SID TY        ID1   ID2    LMODE    REQUEST  CTIME     BLOCK ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 0000000090D8FC88 0000000090D8FCE0   37 AE        100     0        4   0   1174 0 00007FF9EEDA7B58 00007FF9EEDA7BB8   37 TM      87108     0        3   0    233 0 00007FF9EEDA7B58 00007FF9EEDA7BB8   37 TM      87106     0        3   0     27 0 000000008F673658 000000008F6736D0   37 TX     131074   908        6   0    233 0

事务锁没有变,但是又多了一个TM锁。

对于TM锁来说,id1的值是对象的ID

SQL> COL OBJECT_NAME FOR A30 SQL> select OBJECT_NAME,OBJECT_ID from dba_objects where owner='SCOTT' AND OBJECT_NAME IN ('DEPT','EMP'); OBJECT_NAME OBJECT_ID ------------------------------ ---------- DEPT     87106 EMP     87108

对于TX锁,id1是通过事务id转换来的。

我们先查看下事务的相关信息

SQL> SELECT addr,xidusn,xidslot,xidsqn FROM V$TRANSACTION; ADDR      XIDUSN    XIDSLOT    XIDSQN ---------------- ---------- ---------- ---------- 000000008F673658   2      2       908

ADDR与TX锁的ADDR对应,XIDUSN表示回滚段编号,XIDSLOT表示事务表上的编号,XIDSQN表示sequence(覆盖次数)

TX锁的id1的值等于XIDUSN*power(2,16)+XIDSLOT

SQL> select 2*power(2,16)+2 from dual; 2*POWER(2,16)+2 ---------------  131074

事务表、回滚块、事务槽 三者之间的关系如下:

Oracle 学习之性能优化(十)锁

对于TX锁,并没有一个视图能提供事务修改了哪些行。行锁的信息是保存在数据块中的。

下面我们将dept的数据块dump出,查看块的详细信息

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bno from dept;        FNO   BNO ---------- ----------  4   135  4   135  4   135  4   135

只占用了一个数据块,将该块dump

SQL> alter system dump datafile 4 block 135; System altered. SQL> SELECT    d.VALUE        || '/'        || LOWER (RTRIM (i.instance, CHR (0)))        || '_ora_'        || p.spid        || '.trc'           trace_file_name   FROM (SELECT p.spid           FROM v$mystat m, v$session s, v$process p          WHERE m.statistic  2    3    4    5    6    7    8    9   10  # = 1 AND s.sid = m.sid AND p.addr = s.paddr) p,        (SELECT t.instance           FROM v$thread t, v$parameter v          WHERE     v.name = 'thread'                AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,        (SELECT VALUE            11   12   13   14   15   16  FROM v$parameter          WHERE name = 'user_dump_dest') d;    17   TRACE_FILE_NAME -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_5593.trc

查看trace文件

Block header dump:  0x01000087  Object id on Block? Y  seg/obj: 0x15442  csc: 0x00.fab7a  itc: 2  flg: E  typ: 1 - DATA      brn: 0  bdba: 0x1000080 ver: 0x01 opc: 0      inc: 0  exflg: 0    Itl           Xid                  Uba         Flag  Lck        Scn/Fsc 0x01   0x0009.002.00000364  0x00c167b0.009a.2e  C---    0  scn 0x0000.000e0ef0 0x02   0x0002.002.0000038c  0x00c00591.0088.26  ----    4  fsc 0x0000.00000000 bdba: 0x01000087 data_block_dump,data header at 0x7f23e518ea64 =============== tsiz: 0x1f98 hsiz: 0x1a pbl: 0x7f23e518ea64      76543210 flag=-------- ntab=1 nrow=4 frre=-1 fsbo=0x1a fseo=0x1f3c avsp=0x1f22 tosp=0x1f22 0xe:pti[0] nrow=4 offs=0 0x12:pri[0] offs=0x1f7e 0x14:pri[1] offs=0x1f68 0x16:pri[2] offs=0x1f54 0x18:pri[3] offs=0x1f3c block_row_dump: tab 0, row 0, @0x1f7e tl: 26 fb: --H-FL-- lb: 0x2  cc: 3 col  0: [ 2]  c1 0b col  1: [10]  41 63 63 6f 75 6e 74 69 6e 67 col  2: [ 8]  4e 45 57 20 59 4f 52 4b tab 0, row 1, @0x1f68 tl: 22 fb: --H-FL-- lb: 0x2  cc: 3 col  0: [ 2]  c1 15 col  1: [ 8]  52 65 73 65 61 72 63 68 col  2: [ 6]  44 41 4c 4c 41 53 tab 0, row 2, @0x1f54 tl: 20 fb: --H-FL-- lb: 0x2  cc: 3 col  0: [ 2]  c1 1f col  1: [ 5]  53 61 6c 65 73 col  2: [ 7]  43 48 49 43 41 47 4f tab 0, row 3, @0x1f3c tl: 24 fb: --H-FL-- lb: 0x2  cc: 3 col  0: [ 2]  c1 29 col  1: [10]  4f 70 65 72 61 74 69 6f 6e 73 col  2: [ 6]  42 4f 53 54 4f 4e end_of_block_dump End dump data blocks tsn: 4 file#: 4 minblk 135 maxblk 135

1)lb: 0x2 表示改行数据被锁定,标志为2,它表示ITL事务槽的第二条事务信息;而第二条事务信息

的flag为空,表示没有提交,所以该行被锁定了(当然我们开需要查看事务表中的提交标志)。

2)Lck=4表示锁定了4行数据。

锁的mode有如下几种

Oracle 学习之性能优化(十)锁

死锁-deadlock
定义:当两个用户希望持有对方的资源时就会发生死锁.
即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚.
例子:
会话1,执行如下操作

SQL> conn scott/tiger Connected. SQL> update dept set dname=lower(dname); 4 rows updated.

会话2,执行如下操作

SQL> conn scott/tiger Connected. SQL> update emp set ename=lower(ename); 14 rows updated.

会话1,再执行对emp的更新

SQL> update emp set ename=lower(ename);

此时会话1被阻塞。

会话2,执行对dept表的更新

SQL>  update dept set dname=lower(dname);

此时会话2也被阻塞,但是会话1会报一个死锁的错误

SQL> update emp set ename=lower(ename); update emp set ename=lower(ename)        * ERROR at line 1: ORA-00060: deadlock detected while waiting for resource

会话1需要提交或者回滚,会话2才能正常执行。

Oracle的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


当前标题:Oracle学习之性能优化(十)锁-创新互联
链接地址:http://cdxtjz.cn/article/giojo.html

其他资讯