面试宝典:Oracle数据库free buffer waits等待事件处理过程

在这里插入图片描述

Oracle 数据库 free buffer waits 等待事件深度解析

1. 等待事件本质

  • free buffer waits
    当数据库进程需要将数据块读入Buffer Cache时,无法找到空闲缓冲区(free buffer) 而发生的等待。表明Buffer Cache无法及时提供可用空间给新数据块使用。
  • 关键特性
    • 直接反映Buffer Cache的I/O压力
    • 通常伴随物理读(physical reads)增加
    • 高频率出现表明内存配置或SQL效率问题
  • 与相关等待的区别
    等待事件触发原因解决方向
    free buffer waitsBuffer Cache空间不足内存优化/SQL调优
    db file sequential read单块物理读等待I/O优化/索引调整
    db file scattered read多块物理读等待全表扫描优化

2. 产生过程详解

用户会话 Buffer Cache DBWR进程 数据文件 请求数据块(如全表扫描) 检查空闲缓冲区 立即提供缓冲区 触发free buffer waits 请求刷新脏块 写入脏块释放空间 写入完成 通知缓冲区释放 分配空闲缓冲区 alt [存在free buffer] [无空闲缓冲区] 读取数据块到缓冲区 返回数据 用户会话 Buffer Cache DBWR进程 数据文件
  1. 会话请求数据块
    会话执行SQL需要读取不在内存中的数据块
  2. Buffer Cache检查
    在LRU列表上查找空闲缓冲区
  3. 空间不足触发等待
    当所有缓冲区都在使用中(脏块或正在使用)
  4. 唤醒DBWR进程
    会话通知DBWR进程写入脏块
  5. DBWR写脏块
    将修改过的数据块写入磁盘
  6. 缓冲区释放
    写入后的缓冲区被标记为空闲
  7. 分配缓冲区
    会话获得空闲缓冲区
  8. 物理读取
    将数据块从磁盘读入缓冲区

3. 高频场景

全表扫描大表
-- 扫描10GB表
SELECT * FROM sales_history WHERE sale_date > SYSDATE-30;
批量DML操作
-- 更新百万行数据
UPDATE transactions SET status='P' WHERE created < SYSDATE-90;
索引重建
-- 重建大索引
ALTER INDEX sales_idx REBUILD ONLINE;
数据加载
-- SQL*Loader直接路径加载
sqlldr user/pwd control=load.ctl direct=true
备份操作
-- RMAN热备份
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

4. 根本原因分类

内存配置问题
问题类型典型案例
Buffer Cache过小SGA_TARGET=8G, db_cache_size=1G → 处理大型数据集不足
内存分配失衡PGA_AGGREGATE_TARGET=10G, db_cache_size=2G → PGA过大挤压Buffer Cache
多池配置不当shared_pool_size=4G, db_cache_size=1G → 共享池过大
SQL效率问题
  • 全表扫描泛滥
    SELECT * FROM 100GB_table;  -- 未使用索引
    
  • 低效连接操作
    SELECT * FROM t1, t2 WHERE t1.id=t2.id;  -- 未优化的笛卡尔积
    
  • 大结果集排序
    SELECT * FROM orders ORDER BY order_date;  -- 10M行排序
    
I/O系统问题
  • 存储性能不足
    机械硬盘(HDD)无法满足高IOPS需求
  • REDO日志瓶颈
    REDO日志组过少或大小不足
  • DBWR配置不当
    SHOW PARAMETER db_writer_processes; -- 单CPU架构设为1
    
对象设计问题
  • 高PCTFREE设置
    CREATE TABLE logs (...) PCTFREE 40;  -- 空间利用率低
    
  • 频繁更新大对象
    LOB列频繁修改 → 产生大量脏块

5. 深度排查流程

步骤1:系统级诊断
-- 确认等待强度
SELECT event, total_waits, time_waited_micro
FROM v$system_event 
WHERE event = 'free buffer waits';

-- 关联内存统计
SELECT 
  (SELECT value FROM v$sysstat WHERE name='physical reads') phys_reads,
  (SELECT value FROM v$sysstat WHERE name='free buffer requested') free_req
FROM dual;
  • 严重性阈值
    time_waited_micro > 60秒/分钟 + phys_reads > 5000/秒
步骤2:内存配置分析
-- SGA配置检查
SELECT * FROM v$sgnfo;

-- Buffer Cache分配
SELECT 
    component,
    ROUND(current_size/1024/1024) size_mb
FROM v$sga_dynamic_components
WHERE component IN ('DEFAULT buffer cache','KEEP buffer cache');

-- 内存建议
SELECT * FROM v$db_cache_advice;
步骤3:定位热点SQL
-- 高物理读SQL
SELECT 
    sql_id,
    sql_text,
    disk_reads,
    buffer_gets,
    ROUND(disk_reads/buffer_gets,4) read_ratio
FROM v$sql
WHERE disk_reads > 100000
ORDER BY disk_reads DESC;

-- ASH分析
SELECT 
    sql_id,
    COUNT(*) waits,
    current_obj#
FROM v$active_session_history
WHERE event = 'free buffer waits'
AND sample_time > SYSDATE - 10/1440
GROUP BY sql_id, current_obj#
ORDER BY waits DESC;
步骤4:对象分析
-- 高物理读对象
SELECT 
    owner,
    object_name,
    object_type,
    logical_reads,
    physical_reads
FROM v$segment_statistics
WHERE physical_reads > 1000000
ORDER BY physical_reads DESC;

-- 表空间I/O
SELECT 
    ts.name tablespace,
    phyrds physical_reads,
    ROUND(phyrds/(phyblkrd+1),2) avg_reads_per_block
FROM v$filestat fs
JOIN v$tablespace ts ON ts.ts# = fs.ts#;
步骤5:I/O系统检查
-- 文件级I/O
SELECT 
    file_name,
    phyrds,
    phywrts,
    ROUND((readtim*1000)/DECODE(phyrds,0,1,phyrds)) avg_read_ms
FROM v$filestat
JOIN dba_data_files USING (file_id);

-- DBWR性能
SELECT 
    process,
    buffers_written,
    write_complete
FROM v$bgprocess 
WHERE name LIKE 'DBW%';
步骤6:等待链分析
-- 会话级等待
SELECT 
    sid,
    sql_id,
    event,
    p1 file#,
    p2 block#,
    p3 blocks
FROM v$session
WHERE event = 'free buffer waits';

-- 阻塞会话
SELECT 
    holding_sid,
    holding_sql_id,
    COUNT(*) contention_count
FROM v$active_session_history
WHERE event = 'free buffer waits'
GROUP BY holding_sid, holding_sql_id
ORDER BY contention_count DESC;
步骤7:高级诊断
-- Buffer Cache转储
ALTER SESSION SET events 'immediate trace name buffers level 10';

-- 检查点诊断
ALTER SESSION SET events 'immediate trace name checkpoint_debug level 5';

6. 根治方案

紧急处置
-- 终止高负载会话
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

-- 强制刷新脏页
ALTER SYSTEM CHECKPOINT;

-- 临时扩大Buffer Cache
ALTER SYSTEM SET db_cache_size=4G SCOPE=MEMORY;
内存优化
-- 永久调整Buffer Cache
ALTER SYSTEM SET db_cache_size=8G SCOPE=SPFILE;

-- 使用多缓冲池
ALTER SYSTEM SET db_keep_cache_size=2G;  -- 保留热点表
ALTER SYSTEM SET db_recycle_cache_size=1G; -- 临时对象

-- 平衡内存分配
ALTER SYSTEM SET pga_aggregate_target=4G;
ALTER SYSTEM SET sga_target=16G;
SQL优化
  • 减少全表扫描
    -- 添加缺失索引
    CREATE INDEX sales_date_idx ON sales(sale_date);
    
  • 批处理优化
    -- 原语句
    DELETE FROM log WHERE created < SYSDATE-365;
    
    -- 分批删除
    BEGIN
      LOOP
        DELETE FROM log 
        WHERE created < SYSDATE-365 
        AND ROWNUM <= 10000;
        EXIT WHEN SQL%ROWCOUNT = 0;
        COMMIT;
      END LOOP;
    END;
    
  • 结果集限制
    SELECT * FROM orders 
    WHERE order_date > SYSDATE-30 
    AND ROWNUM <= 1000;  -- 限制返回行数
    
对象优化
-- 分区大表
CREATE TABLE sales (...) 
PARTITION BY RANGE (sale_date) (
  PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01','YYYY-MM-DD'))
);

-- 压缩表
ALTER TABLE sales_history COMPRESS FOR OLTP;

-- 调整PCTFREE
ALTER TABLE orders PCTFREE 10;  -- 原值40
I/O系统优化
-- 增加DBWR进程
ALTER SYSTEM SET db_writer_processes=4 SCOPE=SPFILE;  -- 多CPU环境

-- 使用异步I/O
ALTER SYSTEM SET disk_asynch_io=TRUE; 

-- 分离REDO日志
ALTER DATABASE ADD LOGFILE GROUP 4 '+FAST_DATA' SIZE 1G;
架构级优化
  • 读写分离
    将报表查询路由到物理备库
  • 内存数据库
    -- 18c+特性
    ALTER TABLE hot_table INMEMORY;
    
  • 列式存储
    -- 12c+ Hybrid Columnar Compression
    ALTER TABLE sales MODIFY COMPRESS FOR QUERY HIGH;
    

根治原则
解决free buffer waits = 扩大有效缓存 + 减少物理I/O + 优化写入机制
核心在于通过内存优化降低磁盘访问需求,这是提升性能的关键路径。

通过此方案可显著降低Buffer Cache争用,提升数据库整体吞吐量。

欢迎关注我的公众号《IT小Chen

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值