外键字段上索引对锁的影响
子表的外键上如果不创建索引,就有可能导致死锁问题
scenario 1: 更新主表主键,子表外键无索引
| 1 | create table t_pri (id number,name varchar2(10)); | 
session 1:
| 1 | XB@xb> select sid from v$mystat where rownum=1; | 
session 2:
| 1 | XB@xb> select sid from v$mystat where rownum=1; | 
session 3:
| 1 | XB@xb> select sid from v$mystat where rownum=1; | 
查看锁信息:
| 1 | SYS@xb> @lock "sid in (41,56,62)" | 
通过上面的结果可以看到,session2在更新主键的时候,子表外键字段上面没有索引,所以会对t_ref表请求一个TM级别的share锁,而优先的session1会话 正在对t_ref做insert的操作,已经在t_ref上加了一个TM级别的Row-X (SX)锁,与share锁是互相排斥,所以session2 hang住。session3对 t_ref做dml操作的时候,同样会请求TM级别的Row-X (SX)锁,则被session2所阻塞。
scenario 2: 删除主表行,子表on delete cascade
| 1 | XB@xb> alter table t_ref drop constraint fk_ref; | 
session 1(sid:62):
| 1 | XB@xb> insert into t_ref values(1,'xb',10); | 
session 2(sid:41):
| 1 | XB@xb> delete from t_pri where id=10; | 
session 3(sid:56):
| 1 | XB@xb> insert into t_ref values(2,'lves',20); | 
查看锁信息:
| 1 | SYS@xb> @lock "sid in (41,56,62)" | 
这里看到session2请求的锁变成了TM级别的S/Row-X (SSX)锁,表示要先读取t_ref全表(share),然后更改部分行数据(SX)。因为外键上有’on delete cascade’,所以回滚session1以后才能继续执行
session 1(sid:62):
| 1 | XB@xb> rollback; | 
session 2(sid:41):
| 1 | XB@xb> delete from t_pri where id=10; | 
session 3(sid:56):
| 1 | XB@xb> insert into t_ref values(2,'lves',20); | 
scenario 3: 更新主表主键,子表外键有索引
| 1 | XB@xb> create index idx_ref on t_ref(pri_id); | 
session 1(sid:62):
| 1 | XB@xb> insert into t_ref values(1,'xb',10); | 
session 2(sid:41):
| 1 | XB@xb> update t_pri set id=10,name='xb2' where id=10; | 
此时session2 并未被堵塞。
Summary:
- 需要在所有的外键上建立索引,可以用以下语句查询
| 1 | select owner, | 
- 更新主表尽量不要更新主键
外键字段上索引对锁的影响
      https://www.xbdba.com/2018/11/14/foreign-key-noindex-lock/