[20250221]library cache bucket mutex等待模式测试脚本.txt
[20250221]library cache bucket mutex等待模式测试脚本.txt
--//以前的测试都是手工操作,操作很繁琐,经常在tmux界面上切换session。
--//写一个测试脚本方便测试。
$ cat lcm.sh
#!/bin/bash
# arg1=mutex_address arg2=offset arg3=monitor_times
offset=${2:-4}
sleeps=${3:-20}
v_addr="0x${1}+${offset}"
echo "begin mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "set *( int *)(${v_addr})=0x7777" -ex "quit" >/dev/null
echo "modify mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
echo sleep $sleeps seconds
(sleep $sleeps ;gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "set *( int *)(${v_addr})=0x0" -ex "quit" > /dev/null) &
sqlplus -s -l scott/book@book01p <<EOF > /dev/null
set echo off head off verify off feedback off define #
variable my_sid number
column spid new_value v_spid
exec :my_sid := userenv('sid');
select p.spid from v\$session s,v\$process p where s.sid = :my_sid and s.paddr=p.addr;
host strace -Ttt -y -f -p #v_spid -o laji.txt 2>&1 &
host sleep 1
select /*+ 9 */ count(*) from dept where deptno = 93834;
quit
EOF
echo "end mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
mv -iv laji.txt mutex$(date +"%Y%m%d%H%M%S").txt
--//简单说明:选择select /*+ 9 */ count(*) from dept where deptno = 93834;这条语句bucket=0.
--//缺省修改该地址偏移量=4,检测时间20秒,修改的值直接写死0x7777。
--// arg1=mutex_address arg2=offset arg3=monitor_times,最后文件保存为mutex$(date +"%Y%m%d%H%M%S").txt
--//必须安装gdb,并且正常使用。要修改define #代替原来的&,避免冲突,因为在sqlplus调用bash shell时需要使用&放在后台执行。
--//写的有点粗糙。host starce 后面加入host sleep 1主要是因为发现后面的sql语句会先于strace执行。
--//里面是sql语句登录后第1次执行,必须软解析,要使用library cache bucket mutex。可以在前面加入alter session set
--//session_cached_cursors=0 ;更加保险。
--//再次提醒千万不要在生产系统尝试使用!!
--//验证测试:
1.环境:
SCOTT@book01p> @ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
2.确定要修改的mutex地址。
SCOTT@book01p> select /*+ 9 */ count(*) from dept where deptno = 93834;
COUNT(*)
----------
0
SCOTT@book01p> @hashz
HASH_VALUE SQL_ID CHILD_NUMBER KGL_BUCKET HASH_HEX SQL_EXEC_START SQL_EXEC_ID
---------- ------------- ------------ ---------- ---------- ------------------- -----------
3403546624 as3g00v5dw000 0 0 cade0000 2025-02-21 16:17:21 16777216
SYS@book> oradebug setmypid
Statement processed.
SYS@book> oradebug dump library_cache 4
Statement processed.
$ grep "^Bucket:" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_10770.trc | head -4
Bucket: #=0 Mutex=0x6cfa1400(1125281431552, 9, 0, 6)
Bucket: #=5 Mutex=0x6cfa14f0(1125281431552, 4, 0, 6)
Bucket: #=17 Mutex=0x6cfa1730(1125281431552, 8, 0, 6)
Bucket: #=39 Mutex=0x6cfa1b50(1125281431552, 4, 0, 6)
--//以上是前面测试的结果,直接找Bucket: #=0 Mutex=0x6cfa1400的语句测试。
--//该sql语句select /*+ 9 */ count(*) from dept where deptno = 93834;的bucket=0.
--//Bucket: #=0 Mutex=0x6cfa1400
--//0x6cfa1400-0x10 = 0x6cfa13f0
3.测试_mutex_wait_scheme=2.
--//_mutex_wait_scheme=2是缺省值:
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000004 0x00000000
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000004 0x00000000
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000005 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221162228.txt'
$ egrep "getrusage" mutex20250221162228.txt
4090 16:22:07.482052 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 39076}, ru_stime={0, 8015}, ...}) = 0 <0.000020>
4090 16:22:08.668687 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 42091}, ru_stime={0, 10792}, ...}) = 0 <0.000009>
4090 16:22:10.681071 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 46590}, ru_stime={0, 13977}, ...}) = 0 <0.000014>
4090 16:22:12.680455 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 49810}, ru_stime={0, 15793}, ...}) = 0 <0.000014>
4090 16:22:14.700046 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 51433}, ru_stime={0, 20818}, ...}) = 0 <0.000014>
4090 16:22:16.707209 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 56275}, ru_stime={0, 23557}, ...}) = 0 <0.000014>
4090 16:22:18.714197 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 63273}, ru_stime={0, 25578}, ...}) = 0 <0.000014>
4090 16:22:20.719146 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 66264}, ru_stime={0, 28197}, ...}) = 0 <0.000013>
4090 16:22:22.727183 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 71892}, ru_stime={0, 29955}, ...}) = 0 <0.000013>
4090 16:22:24.729607 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 74703}, ru_stime={0, 33689}, ...}) = 0 <0.000014>
4090 16:22:26.736605 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78728}, ru_stime={0, 36336}, ...}) = 0 <0.000014>
4090 16:22:27.190076 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78736}, ru_stime={0, 37854}, ...}) = 0 <0.000007>
4090 16:22:27.191199 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78919}, ru_stime={0, 37942}, ...}) = 0 <0.000006>
4090 16:22:27.195224 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78959}, ru_stime={0, 37961}, ...}) = 0 <0.000008>
4090 16:22:27.196208 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 80047}, ru_stime={0, 37961}, ...}) = 0 <0.000008>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221162228.txt |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c
1 getrusage(0x1
2 sched_yield()
81 semtimedop(98304,
1 getrusage(0x1
129 semtimedop(98304,
1 getrusage(0x1
84 semtimedop(98304,
1 getrusage(0x1
111 semtimedop(98304,
1 getrusage(0x1
119 semtimedop(98304,
1 getrusage(0x1
134 semtimedop(98304,
1 getrusage(0x1
98 semtimedop(98304,
1 getrusage(0x1
123 semtimedop(98304,
1 getrusage(0x1
119 semtimedop(98304,
1 getrusage(0x1
124 semtimedop(98304,
1 getrusage(0x1
44 semtimedop(98304,
4 getrusage(0x1
--//开始2次sched_yield,采用semtimedop休眠,如此循环。
$ egrep "semtimedop" mutex20250221162228.txt| head -3
4090 16:22:07.482361 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.009582>
4090 16:22:07.492051 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.014498>
4090 16:22:07.506732 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.011557>
--//时间是{0, 10000000},前者是秒,后面是纳秒。10000000/10^9 = .01 ,相当于10毫秒。
$ egrep "semtimedop|sched_yield|select" mutex20250221162228.txt|wc
1168 18668 152856
--//休眠1168次。前面记录0x00000490 = 1168,完全一致。
4.测试_mutex_wait_scheme=1.
SYS@book> alter system set "_mutex_wait_scheme"=1 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000006 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000006 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221162924.txt'
$ egrep "getrusage" 'mutex20250221162924.txt'
4311 16:29:04.215070 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19086}, ru_stime={0, 7798}, ...}) = 0 <0.000015>
4311 16:29:04.215204 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19086}, ru_stime={0, 7798}, ...}) = 0 <0.000013>
4311 16:29:05.361880 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 36767}, ru_stime={0, 15757}, ...}) = 0 <0.000009>
4311 16:29:07.377948 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 55633}, ru_stime={0, 27816}, ...}) = 0 <0.000009>
4311 16:29:09.382434 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 70886}, ru_stime={0, 46348}, ...}) = 0 <0.000014>
4311 16:29:11.382197 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 89110}, ru_stime={0, 53466}, ...}) = 0 <0.000014>
4311 16:29:13.383764 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 107836}, ru_stime={0, 74137}, ...}) = 0 <0.000009>
4311 16:29:15.396900 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 116985}, ru_stime={0, 80218}, ...}) = 0 <0.000015>
4311 16:29:17.403258 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 125922}, ru_stime={0, 93542}, ...}) = 0 <0.000013>
4311 16:29:19.414202 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 128673}, ru_stime={0, 102938}, ...}) = 0 <0.000014>
4311 16:29:21.415667 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 131408}, ru_stime={0, 113157}, ...}) = 0 <0.000014>
4311 16:29:23.434382 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 149940}, ru_stime={0, 134562}, ...}) = 0 <0.000007>
4311 16:29:23.891391 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152444}, ru_stime={0, 141011}, ...}) = 0 <0.000008>
4311 16:29:23.892466 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152581}, ru_stime={0, 141138}, ...}) = 0 <0.000006>
4311 16:29:23.896382 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152610}, ru_stime={0, 141164}, ...}) = 0 <0.000007>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221162924.txt |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c
2 getrusage(0x1
1 sched_yield()
563 select(0,
1 getrusage(0x1
642 select(0,
1 getrusage(0x1
698 select(0,
1 getrusage(0x1
466 select(0,
1 getrusage(0x1
825 select(0,
1 getrusage(0x1
308 select(0,
1 getrusage(0x1
414 select(0,
1 getrusage(0x1
232 select(0,
1 getrusage(0x1
247 select(0,
1 getrusage(0x1
769 select(0,
1 getrusage(0x1
245 select(0,
3 getrusage(0x1
--//开始1次sched_yield,采用select休眠,如此循环。
$ egrep "select" 'mutex20250221162924.txt'| head -3
4311 16:29:04.215383 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001700>
4311 16:29:04.217165 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001122>
4311 16:29:04.218381 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001717>
--//时间是{0, 1000},前者是秒,后面是微秒。1000/10^6 = .001秒 ,相当于1毫秒。
$ egrep "semtimedop|sched_yield|select" 'mutex20250221162924.txt'|wc
5410 64914 432775
--//0x000019b2-0x490 = 5410,前面的输出记录前面相减正好也是5410.
5.测试_mutex_wait_scheme=0.
SYS@book> alter system set "_mutex_wait_scheme"=0 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000008 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221163433.txt'
$ egrep "getrusage" 'mutex20250221163433.txt'
4431 16:34:12.806912 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19180}, ru_stime={0, 14571}, ...}) = 0 <0.000018>
4431 16:34:12.807044 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19180}, ru_stime={0, 14571}, ...}) = 0 <0.000013>
4431 16:34:13.986557 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 128699}, ru_stime={0, 83541}, ...}) = 0 <0.000008>
4431 16:34:15.989945 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 191514}, ru_stime={0, 142765}, ...}) = 0 <0.000007>
4431 16:34:17.993149 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 273577}, ru_stime={0, 209624}, ...}) = 0 <0.000010>
4431 16:34:19.994035 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 368504}, ru_stime={0, 295521}, ...}) = 0 <0.000007>
4431 16:34:21.996906 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 474400}, ru_stime={0, 368316}, ...}) = 0 <0.000009>
4431 16:34:23.001664 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 515769}, ru_stime={0, 407250}, ...}) = 0 <0.000010>
4431 16:34:25.003146 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 575372}, ru_stime={0, 456413}, ...}) = 0 <0.000014>
4431 16:34:27.026933 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 627941}, ru_stime={0, 495616}, ...}) = 0 <0.000014>
4431 16:34:29.032056 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 727438}, ru_stime={0, 567155}, ...}) = 0 <0.000012>
4431 16:34:31.051320 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 801699}, ru_stime={0, 616884}, ...}) = 0 <0.000011>
4431 16:34:32.510836 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 919641}, ru_stime={0, 703181}, ...}) = 0 <0.000006>
4431 16:34:32.515097 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 920391}, ru_stime={0, 703181}, ...}) = 0 <0.000006>
4431 16:34:32.515681 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 920674}, ru_stime={0, 703181}, ...}) = 0 <0.000005>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' 'mutex20250221163433.txt' |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c| head -10
2 getrusage(0x1
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
--//99次sched_yield(),1次select,如此循环,到2秒之后调用getrusage。
$ egrep "semtimedop|sched_yield|select" 'mutex20250221163433.txt'|wc
196800 1192608 10873200
--//0x00001a72-0x000019b2 = 0xc0= 192,以前测试已经说明单次测试最大记录sleeps 0xffff,大于该值就溢出了,仅仅记录后4位。
--//196800 = 0x300c0,前面的3丢失了,真实的环境很少出现这样的情况。
SYS@book> @ mutexprofz idn,hash,loc,req,blk,maddr "idn=0"
-- MutexProf by Tanel Poder (http://www.tanelpoder.com)
-- Showing profile of top 50 sleeps...
-- column info : id idn hash hash_value=>hash_value ts=>sleep_timestamp
-- req=>requesting_session blk=>blocking_session val=>mutex_value maddr=>mutex_addr
SUM_SLEEPS GETS_DIFF MUTEX_TYPE IDN HASH GET_LOCATION REQ BLK mutex_addr OBJECT_NAME
---------- -------------- --------------- ---------- ---------- --------------------------------- ---------- ---------- -------------------- -----------------
192 Library Cache 0 kglhdgn1 62 156 30583 000000006CFA1400 (name not found)
--//每次登录执行的sid不变,仅仅记录最后的情况。blk=30583 = 0x7777
6.测试修改mutext值的0-3字节。
SYS@book> alter system set "_mutex_wait_scheme"=2 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 0 5
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000014 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00007777 0x00000000 0x00000014 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 5 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000015 0x0000c854
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221171440.txt'
$ egrep "getrusage" mutex20250221171440.txt
5088 17:14:34.993468 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 24405}, ru_stime={0, 8919}, ...}) = 0 <0.000014>
5088 17:14:34.993582 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 24405}, ru_stime={0, 8919}, ...}) = 0 <0.000012>
5088 17:14:36.335821 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 261605}, ru_stime={0, 101049}, ...}) = 0 <0.000005>
5088 17:14:38.336613 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 621233}, ru_stime={0, 215673}, ...}) = 0 <0.000006>
5088 17:14:39.645600 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843491}, ru_stime={0, 304561}, ...}) = 0 <0.000005>
5088 17:14:39.646849 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843702}, ru_stime={0, 304637}, ...}) = 0 <0.000005>
5088 17:14:39.650208 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843734}, ru_stime={0, 304648}, ...}) = 0 <0.000006>
5088 17:14:39.650780 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 844098}, ru_stime={0, 304780}, ...}) = 0 <0.000005>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221171440.txt | egrep "semtimedop|getrusage|sched_yield|select" | uniq -c| head -10
2 getrusage(0x1
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
--//99次sched_yield(),1次select,如此循环,到2秒之后调用getrusage。类似_mutex_wait_scheme=0.
$ egrep "semtimedop|sched_yield|select" mutex20250221171440.txt|wc
110050 666900 6080250
--//0x0000c854-0x00001a72 = 0xade2= 44514.以前测试已经说明单次测试最大记录sleeps 0xffff,大于该值就溢出了,仅仅记录后4位。
--//110050 = 0x1ade2,前面的1丢失了,真实的环境很少出现这样的情况。
SYS@book> @ mutexprofz idn,hash,loc,req,blk,maddr "idn=0"
-- MutexProf by Tanel Poder (http://www.tanelpoder.com)
-- Showing profile of top 50 sleeps...
-- column info : id idn hash hash_value=>hash_value ts=>sleep_timestamp
-- req=>requesting_session blk=>blocking_session val=>mutex_value maddr=>mutex_addr
SUM_SLEEPS GETS_DIFF MUTEX_TYPE IDN HASH GET_LOCATION REQ BLK mutex_addr OBJECT_NAME
---------- -------------- --------------- ---------- ---------- --------------------------------- ---------- ---------- -------------------- ----------------
44514 Library Cache 0 kglhdgn1 62 156 0 000000006CFA1400 (name not found)
--//以前的测试都是手工操作,操作很繁琐,经常在tmux界面上切换session。
--//写一个测试脚本方便测试。
$ cat lcm.sh
#!/bin/bash
# arg1=mutex_address arg2=offset arg3=monitor_times
offset=${2:-4}
sleeps=${3:-20}
v_addr="0x${1}+${offset}"
echo "begin mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "set *( int *)(${v_addr})=0x7777" -ex "quit" >/dev/null
echo "modify mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
echo sleep $sleeps seconds
(sleep $sleeps ;gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "set *( int *)(${v_addr})=0x0" -ex "quit" > /dev/null) &
sqlplus -s -l scott/book@book01p <<EOF > /dev/null
set echo off head off verify off feedback off define #
variable my_sid number
column spid new_value v_spid
exec :my_sid := userenv('sid');
select p.spid from v\$session s,v\$process p where s.sid = :my_sid and s.paddr=p.addr;
host strace -Ttt -y -f -p #v_spid -o laji.txt 2>&1 &
host sleep 1
select /*+ 9 */ count(*) from dept where deptno = 93834;
quit
EOF
echo "end mutex value :"
gdb -q -batch -p $(pgrep -f ora_mmon_${ORACLE_SID}) -ex "x/8wx 0x${1}" -ex "quit" | grep "^0x" | grep -v "^0x0"
mv -iv laji.txt mutex$(date +"%Y%m%d%H%M%S").txt
--//简单说明:选择select /*+ 9 */ count(*) from dept where deptno = 93834;这条语句bucket=0.
--//缺省修改该地址偏移量=4,检测时间20秒,修改的值直接写死0x7777。
--// arg1=mutex_address arg2=offset arg3=monitor_times,最后文件保存为mutex$(date +"%Y%m%d%H%M%S").txt
--//必须安装gdb,并且正常使用。要修改define #代替原来的&,避免冲突,因为在sqlplus调用bash shell时需要使用&放在后台执行。
--//写的有点粗糙。host starce 后面加入host sleep 1主要是因为发现后面的sql语句会先于strace执行。
--//里面是sql语句登录后第1次执行,必须软解析,要使用library cache bucket mutex。可以在前面加入alter session set
--//session_cached_cursors=0 ;更加保险。
--//再次提醒千万不要在生产系统尝试使用!!
--//验证测试:
1.环境:
SCOTT@book01p> @ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID : 0
PL/SQL procedure successfully completed.
2.确定要修改的mutex地址。
SCOTT@book01p> select /*+ 9 */ count(*) from dept where deptno = 93834;
COUNT(*)
----------
0
SCOTT@book01p> @hashz
HASH_VALUE SQL_ID CHILD_NUMBER KGL_BUCKET HASH_HEX SQL_EXEC_START SQL_EXEC_ID
---------- ------------- ------------ ---------- ---------- ------------------- -----------
3403546624 as3g00v5dw000 0 0 cade0000 2025-02-21 16:17:21 16777216
SYS@book> oradebug setmypid
Statement processed.
SYS@book> oradebug dump library_cache 4
Statement processed.
$ grep "^Bucket:" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_10770.trc | head -4
Bucket: #=0 Mutex=0x6cfa1400(1125281431552, 9, 0, 6)
Bucket: #=5 Mutex=0x6cfa14f0(1125281431552, 4, 0, 6)
Bucket: #=17 Mutex=0x6cfa1730(1125281431552, 8, 0, 6)
Bucket: #=39 Mutex=0x6cfa1b50(1125281431552, 4, 0, 6)
--//以上是前面测试的结果,直接找Bucket: #=0 Mutex=0x6cfa1400的语句测试。
--//该sql语句select /*+ 9 */ count(*) from dept where deptno = 93834;的bucket=0.
--//Bucket: #=0 Mutex=0x6cfa1400
--//0x6cfa1400-0x10 = 0x6cfa13f0
3.测试_mutex_wait_scheme=2.
--//_mutex_wait_scheme=2是缺省值:
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000004 0x00000000
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000004 0x00000000
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000005 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221162228.txt'
$ egrep "getrusage" mutex20250221162228.txt
4090 16:22:07.482052 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 39076}, ru_stime={0, 8015}, ...}) = 0 <0.000020>
4090 16:22:08.668687 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 42091}, ru_stime={0, 10792}, ...}) = 0 <0.000009>
4090 16:22:10.681071 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 46590}, ru_stime={0, 13977}, ...}) = 0 <0.000014>
4090 16:22:12.680455 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 49810}, ru_stime={0, 15793}, ...}) = 0 <0.000014>
4090 16:22:14.700046 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 51433}, ru_stime={0, 20818}, ...}) = 0 <0.000014>
4090 16:22:16.707209 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 56275}, ru_stime={0, 23557}, ...}) = 0 <0.000014>
4090 16:22:18.714197 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 63273}, ru_stime={0, 25578}, ...}) = 0 <0.000014>
4090 16:22:20.719146 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 66264}, ru_stime={0, 28197}, ...}) = 0 <0.000013>
4090 16:22:22.727183 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 71892}, ru_stime={0, 29955}, ...}) = 0 <0.000013>
4090 16:22:24.729607 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 74703}, ru_stime={0, 33689}, ...}) = 0 <0.000014>
4090 16:22:26.736605 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78728}, ru_stime={0, 36336}, ...}) = 0 <0.000014>
4090 16:22:27.190076 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78736}, ru_stime={0, 37854}, ...}) = 0 <0.000007>
4090 16:22:27.191199 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78919}, ru_stime={0, 37942}, ...}) = 0 <0.000006>
4090 16:22:27.195224 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 78959}, ru_stime={0, 37961}, ...}) = 0 <0.000008>
4090 16:22:27.196208 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 80047}, ru_stime={0, 37961}, ...}) = 0 <0.000008>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221162228.txt |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c
1 getrusage(0x1
2 sched_yield()
81 semtimedop(98304,
1 getrusage(0x1
129 semtimedop(98304,
1 getrusage(0x1
84 semtimedop(98304,
1 getrusage(0x1
111 semtimedop(98304,
1 getrusage(0x1
119 semtimedop(98304,
1 getrusage(0x1
134 semtimedop(98304,
1 getrusage(0x1
98 semtimedop(98304,
1 getrusage(0x1
123 semtimedop(98304,
1 getrusage(0x1
119 semtimedop(98304,
1 getrusage(0x1
124 semtimedop(98304,
1 getrusage(0x1
44 semtimedop(98304,
4 getrusage(0x1
--//开始2次sched_yield,采用semtimedop休眠,如此循环。
$ egrep "semtimedop" mutex20250221162228.txt| head -3
4090 16:22:07.482361 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.009582>
4090 16:22:07.492051 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.014498>
4090 16:22:07.506732 semtimedop(98304, {{65, -1, 0}}, 1, {0, 10000000}) = -1 EAGAIN (Resource temporarily unavailable) <0.011557>
--//时间是{0, 10000000},前者是秒,后面是纳秒。10000000/10^9 = .01 ,相当于10毫秒。
$ egrep "semtimedop|sched_yield|select" mutex20250221162228.txt|wc
1168 18668 152856
--//休眠1168次。前面记录0x00000490 = 1168,完全一致。
4.测试_mutex_wait_scheme=1.
SYS@book> alter system set "_mutex_wait_scheme"=1 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000006 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000006 0x00000490
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221162924.txt'
$ egrep "getrusage" 'mutex20250221162924.txt'
4311 16:29:04.215070 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19086}, ru_stime={0, 7798}, ...}) = 0 <0.000015>
4311 16:29:04.215204 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19086}, ru_stime={0, 7798}, ...}) = 0 <0.000013>
4311 16:29:05.361880 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 36767}, ru_stime={0, 15757}, ...}) = 0 <0.000009>
4311 16:29:07.377948 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 55633}, ru_stime={0, 27816}, ...}) = 0 <0.000009>
4311 16:29:09.382434 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 70886}, ru_stime={0, 46348}, ...}) = 0 <0.000014>
4311 16:29:11.382197 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 89110}, ru_stime={0, 53466}, ...}) = 0 <0.000014>
4311 16:29:13.383764 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 107836}, ru_stime={0, 74137}, ...}) = 0 <0.000009>
4311 16:29:15.396900 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 116985}, ru_stime={0, 80218}, ...}) = 0 <0.000015>
4311 16:29:17.403258 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 125922}, ru_stime={0, 93542}, ...}) = 0 <0.000013>
4311 16:29:19.414202 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 128673}, ru_stime={0, 102938}, ...}) = 0 <0.000014>
4311 16:29:21.415667 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 131408}, ru_stime={0, 113157}, ...}) = 0 <0.000014>
4311 16:29:23.434382 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 149940}, ru_stime={0, 134562}, ...}) = 0 <0.000007>
4311 16:29:23.891391 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152444}, ru_stime={0, 141011}, ...}) = 0 <0.000008>
4311 16:29:23.892466 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152581}, ru_stime={0, 141138}, ...}) = 0 <0.000006>
4311 16:29:23.896382 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 152610}, ru_stime={0, 141164}, ...}) = 0 <0.000007>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221162924.txt |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c
2 getrusage(0x1
1 sched_yield()
563 select(0,
1 getrusage(0x1
642 select(0,
1 getrusage(0x1
698 select(0,
1 getrusage(0x1
466 select(0,
1 getrusage(0x1
825 select(0,
1 getrusage(0x1
308 select(0,
1 getrusage(0x1
414 select(0,
1 getrusage(0x1
232 select(0,
1 getrusage(0x1
247 select(0,
1 getrusage(0x1
769 select(0,
1 getrusage(0x1
245 select(0,
3 getrusage(0x1
--//开始1次sched_yield,采用select休眠,如此循环。
$ egrep "select" 'mutex20250221162924.txt'| head -3
4311 16:29:04.215383 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001700>
4311 16:29:04.217165 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001122>
4311 16:29:04.218381 select(0, [], [], [], {0, 1000}) = 0 (Timeout) <0.001717>
--//时间是{0, 1000},前者是秒,后面是微秒。1000/10^6 = .001秒 ,相当于1毫秒。
$ egrep "semtimedop|sched_yield|select" 'mutex20250221162924.txt'|wc
5410 64914 432775
--//0x000019b2-0x490 = 5410,前面的输出记录前面相减正好也是5410.
5.测试_mutex_wait_scheme=0.
SYS@book> alter system set "_mutex_wait_scheme"=0 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 4 20
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00000000 0x00007777 0x00000007 0x000019b2
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 20 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000008 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221163433.txt'
$ egrep "getrusage" 'mutex20250221163433.txt'
4431 16:34:12.806912 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19180}, ru_stime={0, 14571}, ...}) = 0 <0.000018>
4431 16:34:12.807044 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 19180}, ru_stime={0, 14571}, ...}) = 0 <0.000013>
4431 16:34:13.986557 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 128699}, ru_stime={0, 83541}, ...}) = 0 <0.000008>
4431 16:34:15.989945 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 191514}, ru_stime={0, 142765}, ...}) = 0 <0.000007>
4431 16:34:17.993149 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 273577}, ru_stime={0, 209624}, ...}) = 0 <0.000010>
4431 16:34:19.994035 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 368504}, ru_stime={0, 295521}, ...}) = 0 <0.000007>
4431 16:34:21.996906 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 474400}, ru_stime={0, 368316}, ...}) = 0 <0.000009>
4431 16:34:23.001664 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 515769}, ru_stime={0, 407250}, ...}) = 0 <0.000010>
4431 16:34:25.003146 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 575372}, ru_stime={0, 456413}, ...}) = 0 <0.000014>
4431 16:34:27.026933 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 627941}, ru_stime={0, 495616}, ...}) = 0 <0.000014>
4431 16:34:29.032056 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 727438}, ru_stime={0, 567155}, ...}) = 0 <0.000012>
4431 16:34:31.051320 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 801699}, ru_stime={0, 616884}, ...}) = 0 <0.000011>
4431 16:34:32.510836 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 919641}, ru_stime={0, 703181}, ...}) = 0 <0.000006>
4431 16:34:32.515097 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 920391}, ru_stime={0, 703181}, ...}) = 0 <0.000006>
4431 16:34:32.515681 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 920674}, ru_stime={0, 703181}, ...}) = 0 <0.000005>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' 'mutex20250221163433.txt' |egrep "semtimedop|getrusage|sched_yield|select" | uniq -c| head -10
2 getrusage(0x1
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
--//99次sched_yield(),1次select,如此循环,到2秒之后调用getrusage。
$ egrep "semtimedop|sched_yield|select" 'mutex20250221163433.txt'|wc
196800 1192608 10873200
--//0x00001a72-0x000019b2 = 0xc0= 192,以前测试已经说明单次测试最大记录sleeps 0xffff,大于该值就溢出了,仅仅记录后4位。
--//196800 = 0x300c0,前面的3丢失了,真实的环境很少出现这样的情况。
SYS@book> @ mutexprofz idn,hash,loc,req,blk,maddr "idn=0"
-- MutexProf by Tanel Poder (http://www.tanelpoder.com)
-- Showing profile of top 50 sleeps...
-- column info : id idn hash hash_value=>hash_value ts=>sleep_timestamp
-- req=>requesting_session blk=>blocking_session val=>mutex_value maddr=>mutex_addr
SUM_SLEEPS GETS_DIFF MUTEX_TYPE IDN HASH GET_LOCATION REQ BLK mutex_addr OBJECT_NAME
---------- -------------- --------------- ---------- ---------- --------------------------------- ---------- ---------- -------------------- -----------------
192 Library Cache 0 kglhdgn1 62 156 30583 000000006CFA1400 (name not found)
--//每次登录执行的sid不变,仅仅记录最后的情况。blk=30583 = 0x7777
6.测试修改mutext值的0-3字节。
SYS@book> alter system set "_mutex_wait_scheme"=2 scope=memory;
System altered.
$ ./lcm.sh 6cfa1400 0 5
begin mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000014 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
modify mutex value :
0x6cfa1400: 0x00007777 0x00000000 0x00000014 0x00001a72
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
sleep 5 seconds
end mutex value :
0x6cfa1400: 0x00000000 0x00000000 0x00000015 0x0000c854
0x6cfa1410: 0x00000000 0x00000000 0x6608b220 0x00000000
'laji.txt' -> 'mutex20250221171440.txt'
$ egrep "getrusage" mutex20250221171440.txt
5088 17:14:34.993468 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 24405}, ru_stime={0, 8919}, ...}) = 0 <0.000014>
5088 17:14:34.993582 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 24405}, ru_stime={0, 8919}, ...}) = 0 <0.000012>
5088 17:14:36.335821 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 261605}, ru_stime={0, 101049}, ...}) = 0 <0.000005>
5088 17:14:38.336613 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 621233}, ru_stime={0, 215673}, ...}) = 0 <0.000006>
5088 17:14:39.645600 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843491}, ru_stime={0, 304561}, ...}) = 0 <0.000005>
5088 17:14:39.646849 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843702}, ru_stime={0, 304637}, ...}) = 0 <0.000005>
5088 17:14:39.650208 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 843734}, ru_stime={0, 304648}, ...}) = 0 <0.000006>
5088 17:14:39.650780 getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 844098}, ru_stime={0, 304780}, ...}) = 0 <0.000005>
--//getrusage的时间间隔2秒。
$ awk '{print $3}' mutex20250221171440.txt | egrep "semtimedop|getrusage|sched_yield|select" | uniq -c| head -10
2 getrusage(0x1
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
1 select(0,
99 sched_yield()
--//99次sched_yield(),1次select,如此循环,到2秒之后调用getrusage。类似_mutex_wait_scheme=0.
$ egrep "semtimedop|sched_yield|select" mutex20250221171440.txt|wc
110050 666900 6080250
--//0x0000c854-0x00001a72 = 0xade2= 44514.以前测试已经说明单次测试最大记录sleeps 0xffff,大于该值就溢出了,仅仅记录后4位。
--//110050 = 0x1ade2,前面的1丢失了,真实的环境很少出现这样的情况。
SYS@book> @ mutexprofz idn,hash,loc,req,blk,maddr "idn=0"
-- MutexProf by Tanel Poder (http://www.tanelpoder.com)
-- Showing profile of top 50 sleeps...
-- column info : id idn hash hash_value=>hash_value ts=>sleep_timestamp
-- req=>requesting_session blk=>blocking_session val=>mutex_value maddr=>mutex_addr
SUM_SLEEPS GETS_DIFF MUTEX_TYPE IDN HASH GET_LOCATION REQ BLK mutex_addr OBJECT_NAME
---------- -------------- --------------- ---------- ---------- --------------------------------- ---------- ---------- -------------------- ----------------
44514 Library Cache 0 kglhdgn1 62 156 0 000000006CFA1400 (name not found)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2021-02-25 [20210224]控制文件序列号满的分析.txt
2021-02-25 [20210225]控制文件序列号满的恢复.txt
2021-02-25 [20210224]fetch r=0算逻辑读吗.txt