[转帖]模拟enq: TX - row lock contention争用

模拟,enq,tx,row,lock,contention · 浏览次数 : 0

小编点评

**内容生成过程** 1. **计算位图值** - 每个会话都计算其位图值。 - 位图值用于计算锁争用。 2. **获取锁** - 每个会话获取锁。 - 每个锁的获得条件包括: -会话状态为等待。 -会话等待的类不是空。 -会话当前线程状态为等待。 3. **执行DML** - 每个会话执行其DML操作。 - DML操作结束后,释放锁。 4. **共享锁** - 每个会话共享其锁。 - 每个锁的获得条件包括: -会话状态为等待。 -会话等待的类不是空。 -会话当前线程状态为等待。 -锁的获得条件满足。 5. **释放锁** - 每个会话释放其锁。 - 每个锁的释放条件包括: -锁的获得条件满足。 -会话状态为等待。 6. **最终结果** - 每个会话最终释放其锁。 - 所有锁释放后,整个数据库处于空闲状态。

正文

https://www.modb.pro/db/623036

 

enq: TX - row lock contention它表示一个事务正在等待另一个事务释放被锁定的行。这种等待事件通常发生在并发访问数据库时,多个事务试图同时修改同一行数据时会发生行级锁争用。

以下是可能导致 “enq: TX - row lock contention” 等待事件的一些常见原因:
1、并发性高:当多个事务同时访问同一行数据时,就会发生锁争用。这种情况通常在高并发应用中发生。
2、事务时间较长:如果一个事务长时间占用某一行或表资源,其他事务就会等待该资源的释放,这也会导致锁争用。
3、索引设计:如果表没有恰当的索引或索引设计不合理,就会导致查询时扫描大量的数据行,从而增加锁争用的可能性。
4、数据库性能问题:如果数据库的性能出现问题,比如CPU使用率过高,I/O等待时间过长等,就会导致锁争用等待事件的发生。

1、当多个session改变同一行时
session 1
SQL> create table test_table (
2 id number primary key,
3 name varchar2(50),
4 value number
5 );

Table created.

SQL> insert into test_table values (1, 'test', 100);

1 row created.

SQL> commit
2 ;

Commit complete.

SQL> update test_table set value = 200 where id = 1;

1 row updated.

session 2

SQL> update test_table set value = 300 where id = 1;

session 3

SQL> @swc sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2 1=1
old 5: REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')
new 5: REPLACE(SYS_CONNECT_BY_PATH(sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2, '->'), '->', ' -> ')
old 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND &2
new 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND 1=1

SESSIONS PATH
---------- --------------------------------------------------------------------------------------------------------------------------------------------
1 -> 254:11896:6f702u1hk7xgg:enq: TX - row lock contention:1415053318:393216 -> 237:20405::SQL*Net message from client:1650815232:1
1 -> 254:11896:6f702u1hk7xgg:enq: TX - row lock contention:1415053318:393216
SQL> select * from v$lock where type in ('TM','TX');

ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007D49C910 000000007D49C940 254 TX 196618 2441 0 6 198 0 0
00007F2437305AC8 00007F2437305AF0 237 TM 76931 0 3 0 203 0 0
00007F2437305AC8 00007F2437305AF0 254 TM 76931 0 3 0 198 0 0
00000000790CD360 00000000790CD398 237 TX 196618 2441 6 0 203 1 0
SQL> select * from v$locked_object;

XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME OS_USER_NAME PROCESS LOCKED_MODE CON_ID
---------- ---------- ---------- ---------- ---------- ------------------------------ -------------------- --------------- ----------- ----------
3 10 2441 76931 237 SYS oracle 8108 3 0
0 0 0 76931 254 SYS oracle 7650 3 0

237和254同时在76931对象上加了3级共享锁,237号会话持有事务

2、当多个session导致唯一键冲突

session 1

SQL> CREATE TABLE test_table (
2 id NUMBER PRIMARY KEY,
3 name VARCHAR2(50) UNIQUE
4 );

Table created.

SQL> INSERT INTO test_table (id, name) VALUES (1, 'test');

1 row created.

session 2

SQL> INSERT INTO test_table (id, name) VALUES (1, 'test');

session 3

SQL> @swc sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2 1=1
old 5: REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')
new 5: REPLACE(SYS_CONNECT_BY_PATH(sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2, '->'), '->', ' -> ')
old 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND &2
new 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND 1=1

SESSIONS PATH
---------- --------------------------------------------------------------------------------------------------------------------------------------------
1 -> 254:11896:5usmba4xn6bwc:enq: TX - row lock contention:1415053316:524291 -> 237:4551::SQL*Net message from client:1650815232:1
1 -> 254:11896:5usmba4xn6bwc:enq: TX - row lock contention:1415053316:524291


SQL> select * from v$lock where type in ('TM','TX') order by sid;

ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007CC26AE8 000000007CC26B20 237 TX 524291 2425 6 0 86 1 0
00007F2437B866F0 00007F2437B86718 237 TM 76933 0 3 0 86 0 0
000000007EF5B3A8 000000007EF5B3E0 254 TX 589855 2470 6 0 79 0 0
000000007D49C4E8 000000007D49C518 254 TX 524291 2425 0 4 79 0 0
00007F2437B866F0 00007F2437B86718 254 TM 76933 0 3 0 79 0 0

237和254同时在对象76933加了共享锁,也同时获得了6级锁,但是254需要申请4级锁导致阻塞

session 1

SQL> commit;

Commit complete.

session 2

SQL> INSERT INTO test_table (id, name) VALUES (1, 'test');
INSERT INTO test_table (id, name) VALUES (1, 'test')
*
ERROR at line 1:
ORA-00001: unique constraint (SYS.SYS_C007696) violated

区别:如果update导致的enq: TX - row lock contention,为数据行上锁导致,与程序设置有关。
如果insert导致enq: TX - row lock contention,则为唯一约束导致的,好的解决方案是使用序列生成唯一键。

session 1

SQL> CREATE SEQUENCE my_sequence
2 START WITH 1
3 INCREMENT BY 1
4 MAXVALUE 999999999
5 CYCLE;

Sequence created.

SQL> INSERT INTO test_table (id, name) VALUES (my_sequence.nextval, 'c');

1 row created.

session 2


SQL> INSERT INTO test_table (id, name) VALUES (my_sequence.nextval, 'd');

1 row created.

session 3

SQL> @swc sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2 1=1
old 5: REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')
new 5: REPLACE(SYS_CONNECT_BY_PATH(sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2, '->'), '->', ' -> ')
old 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND &2
new 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND 1=1

no rows selected

session 1 提交

SQL> commit;

Commit complete.

session 2 提交

SQL> commit;

Commit complete.

SQL> select * from SQL> commit;
select * from SQL> commit
*
ERROR at line 1:
ORA-00933: SQL command not properly ended


SQL>
SQL> Commit complete.
2
SQL>
SQL> select * from test_table;

ID NAME
---------- ----------------------------------------------------------------------------------------------------
6 c
7 d

测试2

SQL> CREATE TABLE test_table (
2 id NUMBER PRIMARY KEY,
3 name VARCHAR2(50)
4 );

Table created.

SQL>
SQL> CREATE BITMAP INDEX test_index ON test_table(name);

Index created.

SQL> INSERT INTO test_table
2 SELECT LEVEL, 'Name' || MOD(LEVEL, 5) FROM DUAL CONNECT BY LEVEL <= 1000000;

1000000 rows created.

SQL> commit;

Commit complete.

session 1

SQL> UPDATE test_table SET name = 'NewName' WHERE name = 'Name1';

session 2

SQL> UPDATE test_table SET name = 'NewName' WHERE name = 'Name2';

session 3

SQL> SELECT * FROM test_table WHERE name = 'Name1' for update;

session 4

SQL> sELECT * FROM test_table WHERE name = 'Name2' for update;

等待

EVENT SID
------------------------------ ----------
enq: TX - row lock contention 35
enq: TX - row lock contention 41
resmgr:cpu quantum 237
resmgr:cpu quantum 254



EVENT SID
------------------------------ ----------
enq: TX - row lock contention 35
enq: TX - row lock contention 41
SQL*Net message from client 237
enq: TX - row lock contention 254
SQL> @swc sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2 1=1
old 5: REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')
new 5: REPLACE(SYS_CONNECT_BY_PATH(sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2, '->'), '->', ' -> ')
old 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND &2
new 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND 1=1

SESSIONS PATH
---------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 -> 254:11896:asyw0r1gaxchh:enq: TX - row lock contention:1415053316:196634
1 -> 41:1567:g9gsass4u3d7z:enq: TX - row lock contention:1415053318:262175
1 -> 41:1567:g9gsass4u3d7z:enq: TX - row lock contention:1415053318:262175 -> 254:11896:asyw0r1gaxchh:enq: TX - row lock contention:1415053316:196634 -> 237:4551:f1dckkc3aj43j:SQL*Net message from client:1650815232:1
1 -> 41:1567:g9gsass4u3d7z:enq: TX - row lock contention:1415053318:262175 -> 254:11896:asyw0r1gaxchh:enq: TX - row lock contention:1415053316:196634
1 -> 254:11896:asyw0r1gaxchh:enq: TX - row lock contention:1415053316:196634 -> 237:4551:f1dckkc3aj43j:SQL*Net message from client:1650815232:1
1 -> 35:61574:c93b0u0y4m43y:enq: TX - row lock contention:1415053318:196634 -> 237:4551:f1dckkc3aj43j:SQL*Net message from client:1650815232:1
1 -> 35:61574:c93b0u0y4m43y:enq: TX - row lock contention:1415053318:196634

7 rows selected.
SQL> select sql_id,sql_text from v$sql where sql_id in ('f1dckkc3aj43j','asyw0r1gaxchh','g9gsass4u3d7z','f1dckkc3aj43j','c93b0u0y4m43y');

SQL_ID SQL_TEXT
-------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
f1dckkc3aj43j UPDATE test_table SET name = 'NewName' WHERE name = 'Name1'
asyw0r1gaxchh UPDATE test_table SET name = 'NewName' WHERE name = 'Name2'
c93b0u0y4m43y SELECT * FROM test_table WHERE name = 'Name1' for update
g9gsass4u3d7z sELECT * FROM test_table WHERE name = 'Name2' for update
SQL> select * from v$lock where type in ('TM','TX') order by type;

ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ---------- ----------
00007FF0C6CE16E0 00007FF0C6CE1708 41 TM 76943 0 3 0 431 0 0
00007FF0C6CE16E0 00007FF0C6CE1708 254 TM 76943 0 3 0 441 0 0
00007FF0C6CE16E0 00007FF0C6CE1708 237 TM 76943 0 3 0 443 0 0
00007FF0C6CE16E0 00007FF0C6CE1708 35 TM 76943 0 3 0 440 0 0
000000007EF5B3A8 000000007EF5B3E0 254 TX 262175 2020 6 0 441 1 0
000000007EF39868 000000007EF398A0 237 TX 196634 2448 6 0 443 1 0
000000007D49C0D8 000000007D49C108 41 TX 262175 2020 0 6 431 0 0
000000007D49BF38 000000007D49BF68 254 TX 196634 2448 0 4 382 0 0
000000007D49BCC8 000000007D49BCF8 35 TX 196634 2448 0 6 440 0 0

9 rows selected.
SQL> select * from v$locked_object;

XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID ORACLE_USERNAME OS_USER_NAME PROCESS LOCKED_MODE CON_ID
---------- ---------- ---------- ---------- ---------- ------------------------------ ------------------------------ ---------- ----------- ----------
0 0 0 76943 35 SYS oracle 7843 3 0
0 0 0 76943 41 SYS oracle 11893 3 0
3 26 2448 76943 237 SYS oracle 8108 3 0
4 31 2020 76943 254 SYS oracle 7650 3 0

锁定的对象还是76943,这次由237阻塞254,254阻塞41,237还阻塞35,
也就是g9gsass4u3d7z–>asyw0r1gaxchh–>f1dckkc3aj43j
四个会话都在76943对象上加了共享锁,254,237加了6级事物锁,237申请4级锁,35、41申请6级锁。
由于每次一行变化都要计算位图值,导致DML本身的性能下降,多个会话同时执行DML时会出现过度的TX锁争用。

commit 237号会话

SQL> @swc sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2 1=1
old 5: REPLACE(SYS_CONNECT_BY_PATH(&1, '->'), '->', ' -> ')
new 5: REPLACE(SYS_CONNECT_BY_PATH(sid||':'||serial#||':'||sql_id||':'||event||':'||p1||':'||p2, '->'), '->', ' -> ')
old 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND &2
new 34: START WITH (ses.state='WAITING' AND ses.wait_class!='Idle') AND 1=1

SESSIONS PATH
---------- -----------------------------------------------------------------------
1 -> 41:1567:g9gsass4u3d7z:enq: TX - row lock contention:1415053318:262175 -> 254:11896:asyw0r1gaxchh:SQL*Net message from client:1650815232:1
1 -> 41:1567:g9gsass4u3d7z:enq: TX - row lock contention:1415053318:262175

与[转帖]模拟enq: TX - row lock contention争用相似的内容:

[转帖]模拟enq: TX - row lock contention争用

https://www.modb.pro/db/623036 enq: TX - row lock contention它表示一个事务正在等待另一个事务释放被锁定的行。这种等待事件通常发生在并发访问数据库时,多个事务试图同时修改同一行数据时会发生行级锁争用。 以下是可能导致 “enq: TX - r

[转帖]Comcast: 模拟糟糕的网络连接,以便构建更好的系统。

https://www.5axxw.com/wiki/content/r0cq99 Comcast 在诸如网络分区和实例终止这样的硬故障下测试分布式系统是至关重要的,但我们在灾难性较小的条件下测试它们也很重要,因为这是它们最常遇到的情况。Comcast是一个用来模拟常见网络问题的工具,如延迟、带宽限

[转帖]全球十大模拟IC厂商排名出炉,TI霸主,微芯上榜

https://www.sohu.com/a/232168751_99984320?qq-pf-to=pcqq.c2c 美高森美和安森美 不是一家.. 前天,IC Insights公布了2017年全球10大模拟芯片厂商营收及排名。据IC Insights统计,2017年全球模拟芯片的市场规模为545

[转帖]jvm学习三-MAT内存分析工具的使用

目录 1 模拟内存溢出程序 1.1 jvm配置 1.2 测试代码 2 MAT工具进行内存分析 2.1 大纲介绍 2.2 Histogram视图介绍 2.3 Leak Suspects视图介绍 2.4 Dominator Tree 1 模拟内存溢出程序 1.1 jvm配置 -XX:+PrintGCDe

[转帖]使用 tc netem 模拟网络异常

https://cizixs.com/2017/10/23/tc-netem-for-terrible-network/ 在某些情况下,我们需要模拟网络很差的状态来测试软件能够正常工作,比如网络延迟、丢包、乱序、重复等。linux 系统强大的流量控制工具 tc 能很轻松地完成,tc 命令行是 ipr

[转帖]巧用Systemtap注入延迟模拟IO设备抖动

http://blog.yufeng.info/archives/2935 原创文章,转载请注明: 转载自系统技术非业余研究 本文链接地址: 巧用Systemtap注入延迟模拟IO设备抖动 当我们的IO密集型的应用怀疑设备的IO抖动,比如说一段时间的wait时间过长导致性能或其他疑难问题的时候,这个

[转帖]【混沌工程】 docker环境下模拟网络延迟和丢包

https://cloud.tencent.com/developer/article/1616202?areaSource=&traceId= 原文地址:https://www.chenquan.me/archives/315 混沌工程最早是Netflix引入的,用来验证服务稳定性的工程。地址:h

[转帖]内存配置+大页 HugePage

内存配置 例1:不加内存参数,模拟一个默认大小内存的客户机系统。 qemu-system-x86_64 /home/dudu/kvm/ubuntu14.04.img 在客户机中,可以通过两种常用的方式来查看内存信息,具体如下: free命令通常用来查看内存的使用情况,“-m”参数是指内存大小以MB为

[转帖]kafka压测多维度分析实战

设置虚拟机不同的带宽来进行模拟压测 kafka数据压测 1、公司生产kafka集群硬盘:单台500G、共3台、日志保留7天。 1.1 版本:1.1.0 2、压测kafka。 2.1 使用kafka自带压测工具:bin/kafka-producer-perf-test.sh 命令参数解释: --num

[转帖]jmeter_采样器sampler简介

1、取样器介绍 取样器是用来模拟用户操作的,向服务器发送请求以及接收服务器的响应数据。 取样器是在线程组内部的元件,也就是说取样器只能在线程组中添加。 取样器(Sampler)是性能测试中向服务器发送请求,记录响应信息,记录响应时间的最小单元。(取样器通常要进行这三个工作) 2、jmeter自带取样