buffer busy waits理解
一.什么是buffer busy waits
当n个进程想以不兼容的模式持有内存块上的buffer pin时,就会产生buffer busy waits等待。
oracle访问/修改数据块的步骤:
1.依据数据块的地址计算出数据块所在的bucket
2.获得保护这个bucket的cbc latch
3.在这个链表上查找需要的数据块,找到后,pin这个buffer(读取s,修改x)
4.释放cbc latch
5.读取/修改数据块的内容
6.获取cbc latch
7.unpin这个buffer
8.释放cbc latch
分析:因为latch的操作都是很短的,上面步骤中除了步骤5,都可以认为是极快的操作。在大并发环境中,如果cbc latch的持有时间过长,会导致大量的latch争用,以致非常容易导致系统的cpu资源出现瓶颈。注意即使所有的操作都是查询非修改,也会导致大量的cbc latch争用:因为cbc latch的持有到cbc latch的释放这段时间太长了。oracle使用在内存块上加buffer pin的方式来解决这个问题。可以看出,这种实现方式使得cbc latch持有期间只做了很少的事情,大大降低了cbc latch的争用。
如果数据库里面读多写少,由于各个读之间的buffer pin时兼容的,都是s模式,因此几乎不会产生任何的争用。
如果数据库里面写多读少,就会产生buffer busy waits等待,但这种等待的代价比cbc latch的等待代价要小的多,因为latch的spin机制是非常耗cpu的,而buffer pin的管理本质上类似于enquen锁的机制,没有spin机制,不需要自旋转消耗大量的cpu。
二.buffer busy waits测试
创建测试表:
SQL> create table test_buffer_busy as select * from dba_objects;Table created.SQL> create index idx_test_buffer_1 on test_buffer_busy(object_id);Index created.
找到同一个块上的两条记录:
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid) fn,dbms_rowid.rowid_block_number(rowid) bl, test_buffer_busy.object_id,rowid from test_buffer_busy where rownum<3;FN BL OBJECT_ID ROWID
---------- ---------- ---------- ------------------4 3131 20 AAAVXOAAEAAAAw7AAA4 3131 46 AAAVXOAAEAAAAw7AAB
1.场景1,读读操作
session1执行:
SQL> select sid from v$mystat where rownum=1;SID
----------1
SQL> declare2 c number;3 begin4 for i in 1 ..6000000 loop5 select count(*) into c from test_buffer_busy where rowid='AAAVXOAAEAAAAw7AAA';6 end loop;7 end;8 /
session2执行:
SQL> select sid from v$mystat where rownum=1;SID
----------37
SQL> declare2 c number;3 begin4 for i in 1 ..6000000 loop5 select count(*) into c from test_buffer_busy where rowid='AAAVXOAAEAAAAw7AAB';6 end loop;7 end;8 /
sesson3观察是否产生buffer busy waits等待事件:
SQL> select event,sid,p1,p2,p3 from v$session_wait where sid in (1,37) and event like '%buffer%';no rows selected
结论:读读场景不会产生任何buffer busy waits等待事件
2.场景2,写写操作
session1:
SQL> begin
for i in 1 ..40000000 loop2 3 UPDATE test_buffer_busy SET object_name=20 where rowid='AAAVXOAAEAAAAw7AAA';4 commit;5 end loop;6 end;7 /
session2:
SQL> begin2 for i in 1 ..40000000 loop3 UPDATE test_buffer_busy SET object_name=46 where rowid='AAAVXOAAEAAAAw7AAB';4 commit;5 end loop;6 end;7 /
session3:
SQL> select event,sid,p1,p2,p3 from v$session_wait where sid in(46,50) and event like '%buffer%';no rows selected
EVENT SID
---------------------------------------------------------------- ----------P1 P2 P3
---------- ---------- ----------
buffer busy waits 464 3131 1buffer busy waits 504 3131 1
参数解释:
p1:数据块驻留的绝对文件号。select file_name,relative_fno from dba_data_files;
p2:进程需要访问的实际数据块号。
p3:块类型编号
1 Data block2 Sort block3 Save undo block4 Segment header5 Save undo header6 Free List7 Extent map8 1st level bitmap block9 2nd level bitmap block10 3rd levelbitmap block11 Bitmapblock12 Bitmapindex block13 Fileheader block14 Unused15 Systemundo block16 Systemundo block17 Undoheader18 Undoblock
查看v$waitstat视图:
SQL> select * from v$waitstat;CLASS COUNT TIME
------------------ ---------- ----------
data block 10349 2399
可以看到data block上面发生了大量等待。
两个session的等待里都有大量的buffer busy waits等待,由于session1和session2在同一个buffer上加x排他的buffer pin,两种锁模式的不兼容导致了争用。
3.场景3,读写操作
session1:
SQL> begin2 for i in 1..40000000 loop3 UPDATE test_buffer_busy SET object_name=20 where rowid='AAAVXOAAEAAAAw7AAA';4 commit;5 end loop;6 end;7 /
session2:
SQL> declare2 c number;3 begin4 for i in 1..6000000 loop5 select count(*)into c from test_buffer_busy where rowid='AAAVXOAAEAAAAw7AAB';6 end loop;7 end;8 /
session3:
SQL> select event,sid,p1,p2,p3 from v$session_wait where sid in (1,37) and event like '%buffer%';EVENT SID
---------------------------------------------------------------- ----------P1 P2 P3
---------- ---------- ----------
latch: cache buffers chains 1
2362473448 177 0buffer busy waits 373 272 35
可以看到,session1没有任何的buffer busy waits等待,而进行读操作的session2,产生了大量的buffer busy waits等待。原理:
(1).当读取的进程发现内存块正在被修改时(x模式的buffer pin),它只能等待而不能clone,因为这个时候内存块正在变化过程中,这个时候clone是不安全的。这个时候,读的进程只能等待buffer busy waits。
(2).当写的进程发现内存块正在被读,这个时候,读时不阻塞写的,因为oracle可以很容易的clone出一个数据块,然后在clone的块上进行写,这个时候clone是安全的,因为读内存块的进程不会去修改数据块,保证了clone的安全性。
三.总结
1.buffer busy waits是产生在buffer block上的等待,由于n个进程想以不兼容的模式获得buffer block上的buffer pin时,进而引起buffer waits等待。
2.buffer block的管理模式类似enq锁,先进先出,由队列记录锁的拥有者和等待者
3.写写,读写操作都会产生buffer busy waits等待。写写的两个会话,都会产生buffer waits等待,而读写的两个会话,只有读的session会产生,因为它不能简单的clone一个数据块,正在发生写的内存块发生clone是不安全的。
4.oracle为了减少cbc latch持有时间过长的问题,以每次访问buffer block的会话获取两次cbc latch,再配合在内存块上加buffer pin来解决这个问题。
buffer busy waits理解相关推荐
- buffer busy waits等待事件案例-vage
讨厌香草冰激凌的汽车与Buffer busy wiats的故事 记得好几年前看到过一个故事,通用公司曾收到一客户的邮件,邮件中客户描述了一个非常奇怪的问题.他们家有晚饭后去吃冰激凌的习惯,如果他们买的 ...
- buffer busy waits等待事件的原因:hot block [转]
http://blog.chinaunix.net/u/24260/showart_456274.html ********************************************** ...
- 前台等待事件 oracle,Oracle等待事件之buffer busy waits
产生原因 官方定义: This wait happens when a session wants to access a database block in the buffer cache but ...
- latch: cache buffers chains 阻塞 buffer busy waits
os: centos 7.4 db: oracle 11.2.0.4 版本 # cat /etc/centos-release CentOS Linux release 7.4.1708 (Core) ...
- buffer busy waits
当进程需要存取SGA中的buffer的时候,它会依次执行如下步骤的操作: 1.获得cache buffers chains latch,遍历那条buffer chain直到找到需要的buffer he ...
- Oracle等待事件(三)—— buffer busy waits 常见原因及对应解决方法
也先看看buffer busy waits在官方文档中的描述 This wait indicates that there are some buffers in the buffer cache t ...
- 等待事件buffer busy waits
转载自:http://blog.csdn.net/cymm_liu/article/details/7968537 非空闲等待之:buffer busy waits buffer busy wait ...
- Buffer Busy Waits的两个结论
官方文档: This wait indicates that there are some buffers in the buffer cache that multiple processes ar ...
- oracle+buffer+busy+wait,Oracle数据库buffer busy wait等待事件 (2)
--查找等待块类型 SELECT 'segment Header' CLASS, a.Segment_Type, a.Segment_Name, a.Partition_Name FROM Dba_S ...
最新文章
- OC 组合实现多继承
- 《javascript设计模式》笔记之第十章 和 第十一章:门面模式和适配器模式
- device:GPU:0 but available devices are [ /job:localhost/replica:0/task:0/dev
- 智能合约重构社会契约 (5)比特犬模型实现智能合约
- 【MM模块】 Info Record 采购信息记录
- linux为什么开机后有多个内核,CentOS7开机界面出现多个内核选项
- 3.注释(代码的整洁之道)
- app上线发布流程_APP上线发布流程
- 一步步编写操作系统 26 打开A20地址线
- IIS错误信息--另一个程序正在使用此文件,进程无法访问!
- 为什么有时不能正确定位到异常的发生位置?
- Java酒店管理系统项目
- python创建一个银行账户类account_银行账户(示例代码)
- CAShapeLayer把图片做成圆形效果
- php mp3播放列表,ubuntu的本地MP3音乐播放器mpd+mpc
- (十)DSP28335基础教程——ECAP实验(超声波测距)
- 【算法】深度搜索(DFS) 和 广度搜索(BFS)
- google maps js v3 api教程(3) -- 创建infowindow
- PHP + elasticsearch的使用方法,PHP使用ES的超级简单方法
- 今天是国际数学日,既是爱因斯坦的生日又是霍金的忌日