博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[20160616]IOT与主外键.txt
阅读量:6526 次
发布时间:2019-06-24

本文共 9195 字,大约阅读时间需要 30 分钟。

[20160616]IOT与主外键.txt

--许多人都知道主外键引起的阻塞或者死锁,如果主表是IOT呢? IOT实际上一种特殊的索引结构,测试看看.

1.环境:

SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

create table p (

  id number(10) primary key,
  v varchar2(10) not null
) organization index;

create table c (

  id number(10) primary key,
  p_id number(10) not null references p(id),
  v varchar2(10) not null
);

insert into p values (1, '1');

insert into p values (2, '2');
insert into c values (1, 1, '1');
insert into c values (2, 1, '2');
insert into c values (3, 2, '3');

create index cpid on c (p_id);

--注意建立了外键索引.

2.测试:

--session 1:
SCOTT@book> @ &r/spid

       SID    SERIAL# SPID       PID  P_SERIAL# C50

---------- ---------- ------ ------- ---------- --------------------------------------------------
       232       1775 61605       21         53 alter system kill session '232,1775' immediate;

SCOTT@book> SELECT * FROM p WHERE id=1 FOR UPDATE;

        ID V
---------- ----------
         1 1

SCOTT@book> @ &r/xid

XIDUSN_XIDSLOT_XIDSQN
------------------------------
10.4.44155

--session 2:

SCOTT@book> @ &r/spid

       SID    SERIAL# SPID       PID  P_SERIAL# C50

---------- ---------- ------ ------- ---------- --------------------------------------------------
        14       1579 61619       25        236 alter system kill session '14,1579' immediate;

SCOTT@book> INSERT INTO c (id, p_id, v) VALUES (12, 2, 'not locked');

1 row created.
--ok!没有问题.
SCOTT@book> INSERT INTO c (id, p_id, v) VALUES (11, 1, 'locked');

--挂起!!!

SCOTT@book> @ &r/viewlock

   SID    SERIAL# USERNAME   OSUSER     MACHINE    MODULE       LOCK_TYPE       MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT

------ ---------- ---------- ---------- ---------- ------------ --------------- ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
    14       1579 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94325      0          SCOTT  TABLE      P                    No    00000000851E4548
    14       1579 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94327      0          SCOTT  TABLE      C                    No    00000000851E4548
    14       1579 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  None       Share      655364     44155                                             No    00000000851E4548
    14       1579 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  Exclusive  None       589844     13261                                             No    00000000851E4548
   232       1775 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  Exclusive  None       655364     44155                                             Yes
   232       1775 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94325      0          SCOTT  TABLE      P                    No
6 rows selected.

--为什么呢?我的理解因为IOT是特殊的索引,也就是P表实际上段不存在,仅仅存在索引段.

SCOTT@book> select * from dba_segments where owner=user and segment_name='P';
no rows selected

SCOTT@book> select * from dba_objects where owner=user and object_name='P';

OWNER  OBJECT_NAME          SUBOBJECT_  OBJECT_ID DATA_OBJECT_ID OBJECT_TYP CREATED             LAST_DDL_TIME       TIMESTAMP           STATUS  T G S  NAMESPACE EDITION_NAME
------ -------------------- ---------- ---------- -------------- ---------- ------------------- ------------------- ------------------- ------- - - - ---------- ------------------------------
SCOTT  P                                    94325                TABLE      2016-06-08 10:26:18 2016-06-08 10:26:18 2016-06-08:10:26:18 VALID   N N N          1

SCOTT@book> select owner,SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK,BYTES,blocks  from dba_segments where owner=user and segment_name like '%94325';

OWNER  SEGMENT_NAME         HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS
------ -------------------- ----------- ------------ ---------- ----------
SCOTT  SYS_IOT_TOP_94325              4          530      65536          8

SCOTT@book> alter system checkpoint;

System altered.

--也就是数据在索引段.通过bbed观察:

BBED> set dba 4,531

        DBA             0x01000213 (16777747 4,531)

BBED> p /d ktbbh.ktbbhitl[1]

struct ktbbhitl[1], 24 bytes                @68
   struct ktbitxid, 8 bytes                 @68
      ub2 kxidusn                           @68       10
      ub2 kxidslt                           @70       4
      ub4 kxidsqn                           @72       44155
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~可以发现在索引段出现一个事务槽,与前面的对应.
   struct ktbituba, 8 bytes                 @76
      ub4 kubadba                           @76       12583551
      ub2 kubaseq                           @80       8662
      ub1 kubarec                           @82       14
   ub2 ktbitflg                             @84       1 (NONE)
   union _ktbitun, 2 bytes                  @86
      sb2 _ktbitfsc                         @86       0
      ub2 _ktbitwrp                         @86       0
   ub4 ktbitbas                             @88       0

--当插入INSERT INTO c (id, p_id, v) VALUES (11, 1, 'locked');时,要检查P的主键是否有事务存在,而P表实际上是IOT表,这样lck的

--标识实际是在索引上.如果换成堆表就不存在这个问题了.

3.继续做一个特殊的例子:

--drop table cheap purge;
--drop table pheap purge;

create table pheap (

  id number(10) ,
  v varchar2(10) not null
);

--先建立索引,注意不唯一.并且包含字段v.再建立约束.

create index pk_pheap on scott.pheap (id,v);
alter table pheap add constraint pk_headp primary key (id) enable validate;

create table cheap (

  id number(10) primary key,
  p_id number(10) not null references pheap(id),
  v varchar2(10) not null
);

insert into pheap values (1, '1');

insert into pheap values (2, '2');
insert into cheap values (1, 1, '1');
insert into cheap values (2, 1, '2');
insert into cheap values (3, 2, '3');

create index cheappid on cheap (p_id);

--session 1:

SCOTT@book(80,113)> update pheap set id=1 ,v='a' WHERE id=1 ;
1 row updated.

SCOTT@book(80,113)> @ &r/xid

XIDUSN_XIDSLOT_XIDSQN
------------------------------
6.29.4198

--session 2:

SCOTT@book(101,57)> INSERT INTO cheap (id, p_id, v) VALUES (12, 2, 'not locked');
1 row created.

SCOTT@book(101,57)> INSERT INTO cheap (id, p_id, v) VALUES (11, 1, 'locked');

--挂起!

SYS@book> @ &r/viewlock

   SID    SERIAL# USERNAME   OSUSER     MACHINE    MODULE       LOCK_TYPE       MODE_HELD  MODE_REQUE LOCK_ID1   LOCK_ID2   OWNER  OBJECT_TYP OBJECT_NAME          BLOCK LOCKWAIT

------ ---------- ---------- ---------- ---------- ------------ --------------- ---------- ---------- ---------- ---------- ------ ---------- -------------------- ----- --------------------
    80        113 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  Exclusive  None       393245     4198                                              Yes
    80        113 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94505      0          SCOTT  TABLE      PHEAP                No
    80        113 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94507      0          SCOTT  TABLE      CHEAP                No
   101         57 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  Exclusive  None       655379     44196                                             No    00000000851E40E8
   101         57 SCOTT      oracle     gxqyydg4   SQL*Plus     TX Transaction  None       Share      393245     4198                                              No    00000000851E40E8
   101         57 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94507      0          SCOTT  TABLE      CHEAP                No    00000000851E40E8
   101         57 SCOTT      oracle     gxqyydg4   SQL*Plus     TM DML(TM)      Row-X (SX) None       94505      0          SCOTT  TABLE      PHEAP                No    00000000851E40E8
7 rows selected.

--因为我修改pheap的索引,导致插入INSERT INTO cheap (id, p_id, v) VALUES (11, 1, 'locked');时阻塞.你可以转储索引看看.

SCOTT@book(80,113)> select owner,SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK,BYTES,blocks  from dba_segments where owner=user and segment_name like 'PK_PHEAP';

OWNER  SEGMENT_NAME         HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS
------ -------------------- ----------- ------------ ---------- ----------
SCOTT  PK_PHEAP                       4          618      65536          8

SYS@book> alter system checkpoint;

System altered.

SYS@book> alter system dump datafile 4 block 619;

System altered.

Block header dump:  0x0100026b

Object id on Block? Y
seg/obj: 0x1712a  csc: 0x03.1553b03e  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1000268 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0x0006.01d.00001066  0x00c004a0.0739.09  ----    2  fsc 0x0010.00000000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Leaf block dump
===============
header address 140177634691684=0x7f7da61f0a64
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 0
kdxconro 3
kdxcofbo 42=0x2a
kdxcofeo 7990=0x1f36
kdxcoavs 7948
kdxlespl 0
kdxlende 1
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[8018] flag: ---D--, lock: 2, len=14
col 0; len 2; (2):  c1 02
col 1; len 1; (1):  31
col 2; len 6; (6):  01 00 02 44 00 00
row#1[7990] flag: ------, lock: 2, len=14
col 0; len 2; (2):  c1 02
col 1; len 1; (1):  61
col 2; len 6; (6):  01 00 02 44 00 00
row#2[8004] flag: ------, lock: 0, len=14
col 0; len 2; (2):  c1 03
col 1; len 1; (1):  32
col 2; len 6; (6):  01 00 02 44 00 01
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 619 maxblk 619

--注意~,xid与前面的可以对上.全表回滚,然后执行如下:

--session 1:

SCOTT@book(80,113)> update pheap set id=1 WHERE id=1 ;
1 row updated.

--//我仅仅修改id,而且前后数组没有变化.注如果执行这样,后面的结果也一样,不会阻塞.

--//SCOTT@book(80,113)> update pheap set id=1 ,v='1' WHERE id=1 ;
--//1 row updated.

SCOTT@book(80,113)> @ &r/xid

XIDUSN_XIDSLOT_XIDSQN
------------------------------
10.33.44192

--session 2:

SCOTT@book(101,57)> INSERT INTO cheap (id, p_id, v) VALUES (11, 1, 'locked');
1 row created.

--可以发现没有阻塞.

SYS@book> alter system checkpoint;

System altered.

SYS@book> alter system dump datafile 4 block 619;

System altered.

--检查转储内容:

Block header dump:  0x0100026b
Object id on Block? Y
seg/obj: 0x1712a  csc: 0x03.1553b03e  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x1000268 ver: 0x01 opc: 0
     inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0x000a.01a.0000ac9d  0x00c00196.21dd.2c  C---    0  scn 0x0003.1553b019

--//可以发现索引上没有相关事务.因为前后修改的指一样.这样就很容易理解前面的SELECT * FROM p WHERE id=1 FOR UPDATE;另外的会

--//话插入INSERT INTO c(id, p_id, v) VALUES (11, 1, 'locked');会出现阻塞.就是因为IOT表本身就是索引结构,SELECT * FROM p
--WHERE id=1 FOR UPDATE;时,事务发生在相关索引段上.而堆表不会.

--当然在应用的表中使用IOT很少,出现主外键也许概率更低.不过理解后面的原理很重要.

转载地址:http://ywibo.baihongyu.com/

你可能感兴趣的文章
高速数论变换(NTT)
查看>>
Springmvc的跳转方式
查看>>
加密原理介绍,代码实现DES、AES、RSA、Base64、MD5
查看>>
LINUX中常用操作命令
查看>>
成都市2014级三诊第16题(理科)
查看>>
python 获取进程pid号
查看>>
链表中插入一个节点的三种情况
查看>>
洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)
查看>>
TCL函数“参数自动补全” 与 “help 信息显示”
查看>>
POJ1050To the Max
查看>>
汇编基础--标识符、标号、伪指令和指令
查看>>
PowerShell与系统开局(下)
查看>>
运维自动化之使用PHP+MYSQL+SHELL打造私有监控系统(四)
查看>>
Go 四篇
查看>>
游戏数值策划-经验值计算公式设计(自百度文库)
查看>>
Spring JDBC模板惯用方式
查看>>
将公用文件夹从Exchange2010迁移到 Exchange 2013
查看>>
UML用例图概要
查看>>
动态规划算法
查看>>
WebService学习总结(二)——WebService相关概念介绍
查看>>