一张记录用户登录退出的表,每天9点会突然慢一下,等待事件为buffer busy wait并发插入量为230左右。oracle使用assm(如图)也就是L3,L2,L1架构理论上100个L1每个L1管理64个块就支持6400并发,实际也是如此吗?
进行插入实验发现,插入都是插入到1个分区里面,我们知道分区是一个接一个分配的,因为还没分配到分区所以才导致插到1个分区里,手动分配好多个分区。不幸的是结果还是一样。
插入实验一:
SQL> create table ye (id int,name char(10)) tablespace ye;
Table created.
[oracle]$cat insert.sh
sqlplus/ as sysdba<
insert into ye values($1,'qqqq');
commit;
exec dbms_lock.sleep(100000) #防止pid不变导致插入同一个数据块
EOF
[oracle]$./insert.sh 1&[oracle]$./insert.sh 2&[oracle]$./insert.sh 3&[oracle]$./insert.sh 4&SQL> /ID FNO BLOCKID ROW_ID---------- ---------- ---------- ----------
1 8 161 0
2 8 171 0
1 8 172 0
3 8 172 1
3 8 178 0
4 8 181 0
5 8 184 0
2 8 185 0
6 8 186 0
7 8 187 0
8 8 188 0
9 8 189 0
10 8 190 0
插入实验二:
SQL> /ID FNO BLOCKID ROW_ID---------- ---------- ---------- ----------
11 8 132 0
66 8 132 1
12 8 133 0
67 8 133 1
12 8 134 0
68 8 134 1
12 8 135 0
69 8 135 1
12 8 136 0
70 8 136 1
13 8 137 0
14 8 138 0
15 8 139 0
16 8 140 0
17 8 141 0
18 8 142 0
19 8 143 0
20 8 144 0
21 8 145 0
22 8 146 0
23 8 147 0
24 8 148 0
25 8 149 0
25 8 150 0
26 8 151 0
27 8 152 0
28 8 153 0
29 8 154 0
30 8 155 0
31 8 156 0
32 8 157 0
33 8 158 0
34 8 159 0
35 8 160 0
1 8 161 0
36 8 161 1
37 8 162 0
38 8 163 0
39 8 164 0
40 8 165 0
4 8 166 0
41 8 167 0
42 8 168 0
43 8 169 0
44 8 170 0
2 8 171 0
45 8 171 1
1 8 172 0
3 8 172 1
46 8 172 2
47 8 173 0
48 8 174 0
49 8 175 0
50 8 176 0
51 8 177 0
3 8 178 0
52 8 178 1
53 8 179 0
54 8 180 0
4 8 181 0
55 8 181 1
56 8 182 0
57 8 183 0
5 8 184 0
58 8 184 1
2 8 185 0
59 8 185 1
6 8 186 0
60 8 186 1
7 8 187 0
61 8 187 1
8 8 188 0
62 8 188 1
9 8 189 0
63 8 189 1
10 8 190 0
63 8 190 1
11 8 191 0
65 8 191 1
79 rows selected.
在进行70次插入发现,block到191之后开始重新向132号块插入了,这也就能解释128,129号块为L1,130是L2,131是L3,128-191,64个块的同时插入不够230并发量所以有些块在插入过程中又有新的会话要插入,所以导致了buffer busy wait,那么为什么只插入前64个块呢?此时可以dump下131号段头块,可以看到前10位为文件号,后面为块地址,正好看到是192号块。插入的时候都是插入到高水位线以下,因此都插到了前64个块。解决方法就是拉高水位线,每天先使用append方式插入数据再删除,结果等待消失。
在总结下,如果块是8K,区大小是1M,高水位就是一64个块为单位依次往后挪,但是每次并发插入其实都只是往64个块插入。
这里还有个问题L1管理64个块是固定的么?
SQL> create table tbs(id int ,name char(10)) tablespace ye1;
Table created.
SQL>alter table tbs allocate extent(size 200m);
Table altered.
SQL> select extent_id,block_id,blocks,file_id from dba_extents where segment_name='TBS' order by 1;
EXTENT_ID BLOCK_ID BLOCKS FILE_ID---------- ---------- ---------- ----------
0 128 8 9
1 256 128 9
2 384 128 9
3 512 128 9
4 640 128 9
5 768 128 9
6 896 128 9
7 1024 128 9
8 1152 128 9
9 1280 128 9
10 1408 128 9
11 1536 128 9
12 1664 128 9
13 1792 128 9
14 1920 128 9
15 2048 128 9
16 2176 128 9
17 2304 128 9
18 2432 128 9
19 2560 128 9
20 2688 128 9
21 2816 128 9
22 2944 128 9
23 3072 128 9
24 3200 128 9
25 3328 128 9
26 3456 128 9
27 3584 128 9
28 3712 128 9
29 3840 128 9
30 3968 128 9
31 4096 128 9
32 4224 128 9
33 4352 128 9
34 4480 128 9
35 4608 128 9
36 4736 128 9
37 4864 128 9
38 4992 128 9
39 5120 128 9
40 5248 128 9
41 5376 128 9
42 5504 128 9
43 5632 128 9
44 5760 128 9
45 5888 128 9
46 6016 128 9
47 6144 128 9
48 6272 128 9
49 6400 128 9
50 6528 128 9
51 6656 128 9
52 6784 128 9
53 6912 128 9
54 7040 128 9
55 7168 128 9
56 7296 128 9
57 7424 1024 9
58 8448 1024 9
59 9472 1024 9
60 10496 1024 9
61 11520 1024 9
62 12544 1024 9
63 13568 1024 9
64 14592 1024 9
65 15616 1024 9
66 16640 1024 9
67 17664 1024 9
68 18688 1024 9
69 19712 1024 9
70 20736 1024 9
71 21760 1024 9
72 22784 1024 9
73 23808 1024 9
74 24832 1024 9
75 rows selected.
dump256和21760号块,发现第一个块的L1是管理64个块第二个是有256个块。经测试8M区大小的分区第8个分区以后L1中数据块的数量就会达到256个块。因此只要建立8m区大小的表空间插入一些数据将高水位抬到第8个分区以后就可以了。