create index online 和create index 不同及注意点

简介: CREATE INDEX ONLINE 锁模式变化模拟 SESSION 139 SQL>  insert into test123   2  select * from dba_objects;   50062 rows inserte...

CREATE INDEX ONLINE 锁模式变化模拟

SESSION 139
SQL>  insert into test123
  2  select * from dba_objects;
 
50062 rows inserted
不提交
SESSION 148
SQL> create index test123_i on test123(owner) online;

回话148堵塞

SQL>  select * from v$lock where sid in ('139','148') order by sid;
 
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
0000000096669B90 0000000096669BB8        139 TM        53479          0          3          0         66          1
00000000966E6578 00000000966E65B0        139 TX       589843        343          6          0         66          0
0000000096669DD0 0000000096669DF8        148 TM        53481          0          4          0         40          0
0000000096669CB0 0000000096669CD8        148 TM        53479          0          2          4         42          0
00000000978E54F0 00000000978E5510        148 DL        53479          0          3          0         42          0
00000000978E53A0 00000000978E53C0        148 DL        53479          0          3          0         42          0

堵塞正是由于
0000000096669CB0 0000000096669CD8        148 TM        53479          0          2          4         42          0
可以看到已经以模式2也就是SS模式获得TM锁,但是期望以模式4获得TM锁也就是S模式,但是在OBJECTS 53479上被139会话以模式3也就是SX模式获得
因为SS和SX兼容所以可以获得,但是如果想获得S模式,S和SX是不兼容,所以堵塞
顺便提一下OBJECT_ID=53479 就是表TEST123,而对象53481是对象SYS_JOURNAL_53480,就是为了保证在建立索引的同时把可能的更改记录到所谓的日志表中
待索引建立完成后同步到日志中,这也是ONLINE建立索引所独有的。
此时我们COMMIT回话139

SQL>  select * from v$lock where sid in ('139','148') order by sid;
 
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
00000000978E53A0 00000000978E53C0        148 DL        53479          0          3          0        821          0
0000000096669DD0 0000000096669DF8        148 TM        53481          0          4          0        819          0
0000000096669CB0 0000000096669CD8        148 TM        53479          0          2          0         14          0
00000000978E54F0 00000000978E5510        148 DL        53479          0          3          0        821          0

一旦提交后期望的锁即可获得,而且获得后会降级为2也就是SS模式而不是S模式

然后我们又在会话139进行多次DML操作,看看CREATE INDEX ONLINE 是否堵塞 随后的DML


SQL>  select * from v$lock where sid in ('139','148') order by sid;
 
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
000000009666A250 000000009666A278        139 TM        53479          0          3          0         84          0
00000000966C0868 00000000966C08A0        139 TX       131088        311          6          0         80          0
0000000096669DD0 0000000096669DF8        148 TM        53481          0          4          0        562          0
00000000978E54F0 00000000978E5510        148 DL        53479          0          3          0        563          0
00000000978E53A0 00000000978E53C0        148 DL        53479          0          3          0        563          0
0000000096669CB0 0000000096669CD8        148 TM        53479          0          2          0        549          0

这里可以看到实际不会堵塞随后的DML操作,因为降级后只需要对TEST123获得SS模式即可,SS模式是SX模式是兼容的。
所以CREATE INDEX ONLINE会
1、如果在本表上有DML没有提交,那么CREATE INDEX ONLINE会等待其提交,因为初始的时候需要以S模式获得表上TM锁,S模式和SX模式不兼容
2、如果获得了表上S模式锁后,也就是进行创建过程中,实际对表的TM S锁已经降级为SS,这个时候就不会堵塞随后的DML了。这也是为什么
CREATE INDEX ONLINE优于CREATE INDEX的地方,他不会堵塞随后的DML,因为TM锁是SS模式而不是S模式。
   但是还是要注意第一点,所以为了保险还是关闭应用建立索引吧,特别是大表,CREATE INDEX ONLINE也不一定保险。

CREATE INDEX  锁模式变化模拟

其实CREATE INDEX 没什么好模拟的,
如果你还有DML操作在表上,那么一定有TX模式的TM锁,建立索引会报错如下
SQL> create index test123_i
  2  on test123(owner);
 
create index test123_i
on test123(owner)
 
ORA-00054: resource busy and acquire with NOWAIT specified

当然如果可以建立索引的话你会看到如下
回话148建立索引,查看其锁TM为模式4及模式S
SQL>  select * from v$lock where sid in ('139','148') order by sid;
 
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
00000000978E53A0 00000000978E53C0        148 DL        53479          0          3          0          6          0
00000000978E54F0 00000000978E5510        148 DL        53479          0          3          0          6          0
00000000966F2BA8 00000000966F2BE0        148 TX       458790        367          6          0          6          0
0000000096669CB0 0000000096669CD8        148 TM           18          0          3          0          6          0
0000000096669B90 0000000096669BB8        148 TM        53479          0          4          0          6          0


回话139进行操作
delete test123;
查看锁模式如下
SQL>  select * from v$lock where sid in ('139','148') order by sid;
 
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
0000000096669DD0 0000000096669DF8        139 TM        53479          0          0          3         15          0
00000000978E54F0 00000000978E5510        148 DL        53479          0          3          0         31          0
0000000096669B90 0000000096669BB8        148 TM        53479          0          4          0         31          1
00000000966F2BA8 00000000966F2BE0        148 TX       458790        367          6          0         31          0
0000000096668868 00000000966688C8        148 TS            4   18509883          6          0         17          0
00000000978E53A0 00000000978E53C0        148 DL        53479          0          3          0         31          0
0000000096669CB0 0000000096669CD8        148 TM           18          0          3          0         31          0

可以看到回话139想以模式3也就是SX模式获得TM锁,但是因为CREATE INDEX 的TM模式是4也就是S模式,是不共享的,所以不能获得,只能堵塞
等待create index 完成,所以CREATE INDEX一定不能再没有确定这个表没有DML操作的情况下使用,除非你确定没有DML操作在这个表上


兼容矩阵

held/get  null  ss   sx   s   ssx   x
null          1    1    1   1     1   1 
ss            1    1    1   1     1
sx            1    1    1
s             1    1         1
ssx          1    1
x             1

相关文章
|
1月前
|
数据库 数据库管理 索引
DROP INDEX
【11月更文挑战第16天】
24 2
|
SQL 数据库
CREATE TABLE
CREATE TABLE
163 0
|
SQL 索引
ORA-01502: index ‘index_name' or partition of such index is in unusable state
错误现象:   今天发布脚本时,一个表插入数据时报如下错误   ORA-01502: index ‘index_name' or partition of such index is in unusable state   ORA-06512: at line 168 错误原因:   这个错误一般是因为索引状态为UNUSABLE引起的。
992 0
|
C++ 关系型数据库 Oracle
You can’t specify target table for update in FROM claus
不能查询一个表然后再修改这个表,在内层查询中嵌套一个查询,认为是查询中间表 update product set company = 'TG' WHERE id in ( SELECT cc.
1376 0
|
开发工具
|
SQL 索引
ORA-01502: index 'INDEX_NAME' or partition of such index is in unusable state
ORA-01502: index 'INDEX_NAME' or partition of such index is in unusable state 原因:   这个错误一般是因为索引状态为UNUSABLE引起的。
1043 0