enq: TM - contention TM 等待事件的原因及模拟(表外键约束无索引导致)
来源:互联网 发布:数据差错检测 编辑:程序博客网 时间:2024/05/07 23:48
近一个客户反映数据库在执行远程INSERT的时候应用反映很慢,在做AWR后发现enq: TM - contention等待事件很高,应该是外键约束上没有建立索引的问题。
下面我来做个实验还原一下当时的现象。
CREATE TABLE supplier
( supplier_id number(10) not null,
supplier_name varchar2(50) not null,
contact_name varchar2(50),
CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);
INSERT INTO supplier VALUES (1, 'Supplier 1', 'Contact 1');
INSERT INTO supplier VALUES (2, 'Supplier 2', 'Contact 2');
COMMIT;
CREATE TABLE product
( product_id number(10) not null,
product_name varchar2(50) not null,
supplier_id number(10) not null,
CONSTRAINT fk_supplier
FOREIGN KEY (supplier_id)
REFERENCES supplier(supplier_id)
ON DELETE CASCADE
);
INSERT INTO product VALUES (1, 'Product 1', 1);
INSERT INTO product VALUES (2, 'Product 2', 1);
INSERT INTO product VALUES (3, 'Product 3', 2);
COMMIT;
然后去执行几条相关的语句
User 1: DELETE supplier WHERE supplier_id = 1;
User 2: DELETE supplier WHERE supplier_id = 2;(现象HANG住)
User 3: INSERT INTO supplier VALUES (5, 'Supplier 5', 'Contact 5');(现象HANG住)
现在检查锁的情况
col event format a20
col type format a10
col object_name a15
col object_type a15
SELECT l.sid, s.blocking_session blocker, s.event, l.type, l.lmode, l.request, o.object_name, o.object_type
FROM v$lock l, dba_objects o, v$session s
WHERE UPPER(s.username) = UPPER('&User')
AND l.id1 = o.object_id (+)
AND l.sid = s.sid
ORDER BY sid, type;
输入 user 的值: test
原值 3: WHERE UPPER(s.username) = UPPER('&User')
新值 3: WHERE UPPER(s.username) = UPPER('test')
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
144 158 enq: TM - contention TM 3 0
SUPPLIER TABLE
144 158 enq: TM - contention TM 0 2
PRODUCT TABLE
153 SQL*Net message from TM 3 0
client
SUPPLIER TABLE
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
153 SQL*Net message from TM 3 0
client
PRODUCT TABLE
153 SQL*Net message from TX 6 0
client
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
158 153 enq: TM - contention TM 0 5
PRODUCT TABLE
158 153 enq: TM - contention TM 3 0
SUPPLIER TABLE
已选择7行。
SQL>
能看到enq: TM - contention TM 等待事件
检查没有索引的外键
SELECT * FROM (
SELECT c.table_name, cc.column_name, cc.position column_position
FROM user_constraints c, user_cons_columns cc
WHERE c.constraint_name = cc.constraint_name
AND c.constraint_type = 'R'
MINUS
SELECT i.table_name, ic.column_name, ic.column_position
FROM user_indexes i, user_ind_columns ic
WHERE i.index_name = ic.index_name
)
ORDER BY table_name, column_position;
TABLE_NAME
------------------------------
COLUMN_NAME
--------------------------------------------------------------------------------
COLUMN_POSITION
---------------
PRODUCT
SUPPLIER_ID
1
建立索引后:
CREATE INDEX fk_supplier ON product (supplier_id);
INSERT INTO supplier VALUES (6, 'Supplier 6', 'Contact 6');
INSERT INTO supplier VALUES (7, 'Supplier 7', 'Contact 7');
User 1: DELETE supplier WHERE supplier_id = 6;
User 2: DELETE supplier WHERE supplier_id = 7;
User 3: INSERT INTO supplier VALUES (8, 'Supplier 8', 'Contact 8');
相关的等待事件消失。
下面我来做个实验还原一下当时的现象。
CREATE TABLE supplier
( supplier_id number(10) not null,
supplier_name varchar2(50) not null,
contact_name varchar2(50),
CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);
INSERT INTO supplier VALUES (1, 'Supplier 1', 'Contact 1');
INSERT INTO supplier VALUES (2, 'Supplier 2', 'Contact 2');
COMMIT;
CREATE TABLE product
( product_id number(10) not null,
product_name varchar2(50) not null,
supplier_id number(10) not null,
CONSTRAINT fk_supplier
FOREIGN KEY (supplier_id)
REFERENCES supplier(supplier_id)
ON DELETE CASCADE
);
INSERT INTO product VALUES (1, 'Product 1', 1);
INSERT INTO product VALUES (2, 'Product 2', 1);
INSERT INTO product VALUES (3, 'Product 3', 2);
COMMIT;
然后去执行几条相关的语句
User 1: DELETE supplier WHERE supplier_id = 1;
User 2: DELETE supplier WHERE supplier_id = 2;(现象HANG住)
User 3: INSERT INTO supplier VALUES (5, 'Supplier 5', 'Contact 5');(现象HANG住)
现在检查锁的情况
col event format a20
col type format a10
col object_name a15
col object_type a15
SELECT l.sid, s.blocking_session blocker, s.event, l.type, l.lmode, l.request, o.object_name, o.object_type
FROM v$lock l, dba_objects o, v$session s
WHERE UPPER(s.username) = UPPER('&User')
AND l.id1 = o.object_id (+)
AND l.sid = s.sid
ORDER BY sid, type;
输入 user 的值: test
原值 3: WHERE UPPER(s.username) = UPPER('&User')
新值 3: WHERE UPPER(s.username) = UPPER('test')
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
144 158 enq: TM - contention TM 3 0
SUPPLIER TABLE
144 158 enq: TM - contention TM 0 2
PRODUCT TABLE
153 SQL*Net message from TM 3 0
client
SUPPLIER TABLE
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
153 SQL*Net message from TM 3 0
client
PRODUCT TABLE
153 SQL*Net message from TX 6 0
client
SID BLOCKER EVENT TYPE LMODE REQUEST
---------- ---------- -------------------- ---------- ---------- ----------
OBJECT_NAME OBJECT_TYPE
--------------- ---------------
158 153 enq: TM - contention TM 0 5
PRODUCT TABLE
158 153 enq: TM - contention TM 3 0
SUPPLIER TABLE
已选择7行。
SQL>
能看到enq: TM - contention TM 等待事件
检查没有索引的外键
SELECT * FROM (
SELECT c.table_name, cc.column_name, cc.position column_position
FROM user_constraints c, user_cons_columns cc
WHERE c.constraint_name = cc.constraint_name
AND c.constraint_type = 'R'
MINUS
SELECT i.table_name, ic.column_name, ic.column_position
FROM user_indexes i, user_ind_columns ic
WHERE i.index_name = ic.index_name
)
ORDER BY table_name, column_position;
TABLE_NAME
------------------------------
COLUMN_NAME
--------------------------------------------------------------------------------
COLUMN_POSITION
---------------
PRODUCT
SUPPLIER_ID
1
建立索引后:
CREATE INDEX fk_supplier ON product (supplier_id);
INSERT INTO supplier VALUES (6, 'Supplier 6', 'Contact 6');
INSERT INTO supplier VALUES (7, 'Supplier 7', 'Contact 7');
User 1: DELETE supplier WHERE supplier_id = 6;
User 2: DELETE supplier WHERE supplier_id = 7;
User 3: INSERT INTO supplier VALUES (8, 'Supplier 8', 'Contact 8');
相关的等待事件消失。
0 0
- enq: TM - contention TM 等待事件的原因及模拟(表外键约束无索引导致)
- enq: TM - contention 等待事件说明
- enq: TM – contention等待事件
- 事务上的等待事件 —— enq: TM - contention
- 解决enq: TM - contention TM 等待事件案例
- Oracle enq: TX contention 和 enq: TM contention 等待事件说明
- Oracle enq: TX contention 和 enq: TM contention 等待事件说明【转自dave偶像大神】
- 转载-enq:TM-contention
- enq:TM-contention
- 深入剖析:insert 的enq: TM – contention
- enq: TS - contention 等待事件
- “enq: TM - contention”锁引起数据库卡死
- 事务上的等待事件 —— enq: TX - contention
- 事务上的等待事件 —— enq: UL - contention
- 段上的等待事件 —— enq: HW - contention
- enq: TX - row lock contention“等待事件的处理
- 段上的等待事件 —— enq: HW - contention
- enq: TX - row lock contention 等待事件
- TDD+结对编程活动分享
- 一种新颖创新的办公室设计风格引领时尚的潮流
- 实现一个方法,搭出最高的一堆箱子,箱堆的高度为每个箱子高度的总和
- 《C++primer(第五版)》学习之路-序
- 内存 地址 分配
- enq: TM - contention TM 等待事件的原因及模拟(表外键约束无索引导致)
- 取消文件夹拒绝访问
- 理解编译器在编译过程中做了什么
- OC之内存管理
- 数据结构与算法分析Java版练习1.13
- 在线调试方案的思考与实践
- Google技巧之inurl
- Android应用程序用户界面(七)
- 【bzoj2818】【GCD】【数论】