解锁性能密码:Linux 环境下 Oracle 大页配置全攻略

发布于:2025-05-13 ⋅ 阅读:(12) ⋅ 点赞:(0)

在 Oracle 数据库运行过程中,内存管理是影响其性能的关键因素之一。大页内存(Large Pages)作为一种优化内存使用的技术,能够显著提升 Oracle 数据库的运行效率。本文将深入介绍大页内存的相关概念,并详细阐述 Oracle 在 Linux 系统上的大页配置过程。​

一、大页内存介绍​

(一)概念​

  大页内存,是指使用比系统默认页面更大的内存页面来管理内存。在传统的内存管理模式下,操作系统使用较小的页面(例如 4KB)来管理内存,而大页内存通常提供 2MB 甚至 1GB 的页面大小。​

    对于大的SGA大小,HugePages可以在虚拟内存管理方面提供实质性的好处。如果没有HugePages, SGA的内存将被划分为4K页面,这些页面必须由Linux内核管理。使用HugePages,页面大小增加到2MB(如果硬件支持,可以配置为1G),从而减少了内核要管理的页面总数,从而减少了在内存中保存页面表所需的内存量。除了这些更改之外,与HugePages关联的内存不能交换出去,这迫使SGA保持内存驻留。内存的节省和页面管理的工作量使得在x86-64架构上运行的Oracle系统几乎必须使用HugePages。

(二)优势​

  1. 减少页表项数量:由于大页内存页面尺寸更大,同样大小的内存使用大页时所需的页表项数量会大幅减少。这可以降低 CPU 在地址转换时对页表的访问次数,从而提高内存访问效率。​
  1. 降低 TLB(Translation Lookaside Buffer,转换后援缓冲器)压力:TLB 用于缓存页表项,以加快内存地址转换速度。大页内存减少了页表项数量,进而降低了 TLB 的负载,减少 TLB 未命中的情况,提升内存访问性能。​
  1. 提升应用程序性能:对于像 Oracle 这样的大型数据库管理系统,频繁的内存操作和数据读写对内存性能要求极高。大页内存能够提供更高效的内存访问,减少内存碎片,从而显著提升 Oracle 数据库的运行性能。​

(三)在 Oracle 数据库中的作用​

Oracle 数据库的 SGA(System Global Area,系统全局区)是数据库运行时最重要的内存区域,用于存储数据库实例的数据和控制信息。将 SGA 放置在大页内存中,可以充分利用大页内存的优势,使 SGA 中的数据访问更加快速和高效,减少内存争用,为数据库的稳定运行和高性能表现提供有力保障。​

    一个大的SGA并不意味着如果不使用HugePages就会出现问题。通常,大型SGA和大量数据库连接的组合会导致问题。要确定当前使用多少内存来支持页表,请在服务器处于正常/重载状态时运行以下命令。

# grep PageTables /proc/meminfo
PageTables:      1244880 kB

注意:自动内存管理(Automatic Memory Management, AMM)与Linux HugePages不兼容,所以除了ASM实例和小型不重要的数据库之外,在Linux上运行的真实数据库上可能不需要AMM。相反,应该使用自动共享内存管理和自动PGA管理,因为它们与HugePages兼容

二、配置大页

运行以下命令确定当前HugePage的使用情况。在Oracle Linux 8上,默认的HugePage大小是2MB。从下面的输出中可以看到,默认情况下没有定义HugePages。

$ grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

根据SGA的大小,您可能希望将Hugepagesize的值增加到1G。

用以下内容创建一个名为“hugepages_setting.sh”的文件。

#!/bin/bash
#
# hugepages_setting.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
   MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
   if [ $MIN_PG -gt 0 ]; then
      NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
   fi
done
# Finish with results
case $KERN in
   '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
          echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
   '2.6' | '3.8' | '3.10' | '4.1' | '4.14' ) echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    *) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End

使文件可执行。

$ chmod u+x hugepages_setting.sh

确保所有Oracle服务在服务器上正常运行,然后运行脚本并记录推荐的“vm.nr_hugepages”价值。

$ ./hugepages_setting.sh 
Recommended setting: vm.nr_hugepages = 305

以“root”用户身份编辑“/etc/sysctl.conf”文件,添加以下条目,并根据脚本的输出进行调整。您应该将值设置为大于或等于脚本显示的值。您只需要 1 或 2 个备用页。

vm.nr_hugepages=306

以“root”用户身份运行以下命令。

# sysctl -p

或者,编辑“/etc/grub.conf”文件,将“hugepages=306”添加到默认内核的内核行末尾,然后重新启动。

您现在可以看到 HugePages 已创建,但当前尚未使用。  

$ grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:     306
HugePages_Free:      306
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

将以下条目添加到“/etc/security/limits.conf”脚本或“/etc/security/limits.d/99-grid-oracle-limits.conf”脚本中,其中设置至少为HugePages 分配(以 KB 为单位)(HugePages * Hugepagesize)。在这种情况下,该值为 306*2048=626688。

* soft memlock 626688
* hard memlock 626688

检查是否未为数据库设置 MEMORY_TARGET 参数,而是使用 SGA_TARGET 和 PGA_AGGREGATE_TARGET 参数。

SQL> show parameter target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
archive_lag_target                   integer     0
db_flashback_retention_target        integer     1440
fast_start_io_target                 integer     0
fast_start_mttr_target               integer     0
memory_max_target                    big integer 0
memory_target                        big integer 0
parallel_servers_target              integer     16
pga_aggregate_target                 big integer 200M
sga_target                           big integer 600M

根据需要重启服务器并重启数据库服务。

再次检查HugePages信息。  

$ grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:     306
HugePages_Free:       98
HugePages_Rsvd:       93
HugePages_Surp:        0
Hugepagesize:       2048 kB

您可以看到 HugePages 现在正在被使用。

三、强制ORACLE使用大页 (USE_LARGE_PAGES)

正确调整 HugePages 的数量非常重要,因为在 11.2.0.3 之前,如果整个 SGA 不适合可用的 HugePages,实例将在不使用任何 HugePages 的情况下启动。从11.2.0.3开始,SGA部分可以运行在HugePages中,部分不能运行,所以这个问题的影响不是很大。不正确的尺寸可能不易被发现。数据库的更高版本在启动期间在警报日志中显示“大页信息”部分。

****************** Large Pages Information *****************

Total Shared Global Region in Large Pages = 602 MB (100%)

Large Pages used by this instance: 301 (602 MB)
Large Pages unused system wide = 5 (10 MB) (alloc incr 4096 KB)
Large Pages configured system wide = 306 (612 MB)
Large Page size = 2048 KB
***********************************************************

如果您运行的是 Oracle 11.2.0.2 或更高版本,则可以将 USE_LARGE_PAGES 初始化参数设置为“only”,这样数据库在没有大页支持的情况下将无法启动。

ALTER SYSTEM SET use_large_pages=only SCOPE=SPFILE;
SHUTDOWN IMMEDIATE;
STARTUP;

启动时,警报日志中的“大页面信息”反映了此参数的使用。

****************** Large Pages Information *****************
Parameter use_large_pages = ONLY

Total Shared Global Region in Large Pages = 602 MB (100%)

Large Pages used by this instance: 301 (602 MB)
Large Pages unused system wide = 5 (10 MB) (alloc incr 4096 KB)
Large Pages configured system wide = 306 (612 MB)
Large Page size = 2048 KB
***********************************************************

当没有足够的 HugePages 来容纳 SGA 时尝试启动数据库现在将返回以下错误。

SQL> STARTUP
ORA-27137: unable to allocate large pages to create a shared memory segment
Linux-x86_64 Error: 12: Cannot allocate memory
SQL> 

警报日志输出的“大页信息”部分描述了启动失败以及要采取的适当操作。

****************** Large Pages Information *****************
Parameter use_large_pages = ONLY

Large Pages unused system wide = 0 (0 KB) (alloc incr 4096 KB)
Large Pages configured system wide = 0 (0 KB)
Large Page size = 2048 KB

ERROR:
  Failed to allocate shared global region with large pages, unix errno = 12.
  Aborting Instance startup.
  ORA-27137: unable to allocate Large Pages to create a shared memory segment

ACTION:
  Total Shared Global Region size is 608 MB. Increase the number of
  unused large pages to atleast 304 (608 MB) to allocate 100% Shared Global
  Region with Large Pages.
***********************************************************

四、禁止透明大页 

从 RHEL6/OL6 开始,默认实现并启用透明大页。它们旨在通过允许“khugpaged”内核线程动态分配 HugePages 来改进内存管理,而不是像传统的 HugePages 那样在启动时分配。这听起来是个好主意,但不幸的是,透明大页不能很好地与 Oracle 数据库配合使用,并且与 RAC 安装中的节点重新启动以及单实例和 RAC 安装中的性能问题相关。因此,Oracle 建议在运行 Oracle 数据库的所有服务器上禁用透明大页。  

五、大页性能测试

以下是一个实验过程,用于证明 Oracle 在 Linux 上开启大页内存配置后能获得明显的性能提升。这个实验设计包含了测试环境准备、测试方案设计、测试执行和结果分析等关键环节。

(一)脚本analyze-results.sh

#!/bin/bash

# Oracle大页内存性能测试 - 结果分析脚本

# 检查参数
if [ -z "$1" ] || [ -z "$2" ]; then
    echo "用法: $0 <非大页测试结果目录> <大页测试结果目录>"
    exit 1
fi

# 定义常量
NON_HUGEPAGES_DIR=$1
HUGEPAGES_DIR=$2
ANALYSIS_DIR="$HOME/hugepages_analysis_$(date +%Y%m%d_%H%M%S)"
RESULT_FILE="$ANALYSIS_DIR/comparison_results.txt"

# 创建分析目录
mkdir -p $ANALYSIS_DIR

# 记录结果函数
record_result() {
    echo "$1" >> $RESULT_FILE
    echo "$1"
}

# 分析测试结果
analyze_test_results() {
    local test_type=$1
    local non_hugepages_files=$(find $NON_HUGEPAGES_DIR -name "${test_type}*.txt" | sort)
    local hugepages_files=$(find $HUGEPAGES_DIR -name "${test_type}*.txt" | sort)
    
    record_result "=== 测试类型: $test_type ==="
    record_result ""
    
    local non_hugepages_total_time=0
    local non_hugepages_count=0
    local hugepages_total_time=0
    local hugepages_count=0
    
    # 计算非大页测试的平均时间
    record_result "非大页测试结果:"
    for file in $non_hugepages_files; do
        # 提取real时间
        real_time=$(grep "real" "$file" | tail -1 | awk '{print $2}')
        # 转换为秒
        minutes=$(echo $real_time | cut -d'm' -f1)
        seconds=$(echo $real_time | cut -d'm' -f2 | cut -d's' -f1)
        total_seconds=$(echo "scale=2; $minutes * 60 + $seconds" | bc)
        
        record_result "  文件: $(basename $file), 执行时间: ${total_seconds}秒"
        non_hugepages_total_time=$(echo "scale=2; $non_hugepages_total_time + $total_seconds" | bc)
        ((non_hugepages_count++))
    done
    
    if [ $non_hugepages_count -gt 0 ]; then
        non_hugepages_avg_time=$(echo "scale=2; $non_hugepages_total_time / $non_hugepages_count" | bc)
        record_result "  平均执行时间: ${non_hugepages_avg_time}秒"
    else
        record_result "  未找到非大页测试结果"
        non_hugepages_avg_time=0
    fi
    
    record_result ""
    
    # 计算大页测试的平均时间
    record_result "大页测试结果:"
    for file in $hugepages_files; do
        # 提取real时间
        real_time=$(grep "real" "$file" | tail -1 | awk '{print $2}')
        # 转换为秒
        minutes=$(echo $real_time | cut -d'm' -f1)
        seconds=$(echo $real_time | cut -d'm' -f2 | cut -d's' -f1)
        total_seconds=$(echo "scale=2; $minutes * 60 + $seconds" | bc)
        
        record_result "  文件: $(basename $file), 执行时间: ${total_seconds}秒"
        hugepages_total_time=$(echo "scale=2; $hugepages_total_time + $total_seconds" | bc)
        ((hugepages_count++))
    done
    
    if [ $hugepages_count -gt 0 ]; then
        hugepages_avg_time=$(echo "scale=2; $hugepages_total_time / $hugepages_count" | bc)
        record_result "  平均执行时间: ${hugepages_avg_time}秒"
    else
        record_result "  未找到大页测试结果"
        hugepages_avg_time=0
    fi
    
    record_result ""
    
    # 计算性能提升百分比
    if [ $non_hugepages_avg_time -gt 0 ] && [ $hugepages_avg_time -gt 0 ]; then
        improvement=$(echo "scale=2; (1 - $hugepages_avg_time / $non_hugepages_avg_time) * 100" | bc)
        record_result "性能提升: ${improvement}%"
    else
        record_result "无法计算性能提升百分比"
    fi
    
    record_result "========================================"
    record_result ""
}

# 主函数
record_result "Oracle大页内存性能测试对比分析"
record_result "测试日期: $(date)"
record_result "非大页测试结果目录: $NON_HUGEPAGES_DIR"
record_result "大页测试结果目录: $HUGEPAGES_DIR"
record_result "----------------------------------------"
record_result ""

# 分析各项测试结果
analyze_test_results "full_table_scan"
analyze_test_results "index_scan"
analyze_test_results "dml_operations"

# 生成图表数据
if [ -f "$RESULT_FILE" ]; then
    # 提取性能提升数据
    grep "性能提升" "$RESULT_FILE" > "$ANALYSIS_DIR/improvement_data.txt"
    
    # 创建简单的性能对比图表
    cat > "$ANALYSIS_DIR/performance_comparison_chart.csv" <<EOF
测试类型,非大页平均时间(秒),大页平均时间(秒),性能提升(%)
全表扫描,$(grep "全表扫描" "$RESULT_FILE" | awk '{print $5}'),$(grep "全表扫描" "$RESULT_FILE" | awk '{print $12}'),$(grep "全表扫描" "$RESULT_FILE" | awk '{print $15}')
索引扫描,$(grep "索引扫描" "$RESULT_FILE" | awk '{print $5}'),$(grep "索引扫描" "$RESULT_FILE" | awk '{print $12}'),$(grep "索引扫描" "$RESULT_FILE" | awk '{print $15}')
DML操作,$(grep "DML操作" "$RESULT_FILE" | awk '{print $5}'),$(grep "DML操作" "$RESULT_FILE" | awk '{print $12}'),$(grep "DML操作" "$RESULT_FILE" | awk '{print $15}')
EOF
    
    record_result "分析完成,结果保存在: $RESULT_FILE"
    record_result "图表数据保存在: $ANALYSIS_DIR/performance_comparison_chart.csv"
fi    

(二)脚本run-performance-tests.sh

#!/bin/bash

# Oracle大页内存性能测试 - 测试执行脚本

# 检查是否为oracle用户
if [ "$(id -un)" != "oracle" ]; then
    echo "请使用oracle用户执行此脚本"
    exit 1
fi

# 定义常量
ORACLE_SID="TESTDB"
ORACLE_HOME="/u01/app/oracle/product/19.3.0/dbhome_1"
TEST_USER="testuser"
TEST_PASS="testuser"
TEST_RUNS=5
TEST_RESULTS_DIR="$HOME/hugepages_test_results"
LOG_FILE="$TEST_RESULTS_DIR/performance_test_$(date +%Y%m%d_%H%M%S).log"

# 创建结果目录
mkdir -p $TEST_RESULTS_DIR

# 记录日志函数
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# 函数:执行SQL测试
run_sql_test() {
    local test_name=$1
    local sql_statement=$2
    local test_file="$TEST_RESULTS_DIR/${test_name}_$(date +%Y%m%d_%H%M%S).txt"
    
    log "开始测试: $test_name"
    
    for ((i=1; i<=$TEST_RUNS; i++)); do
        log "  测试运行 #$i"
        
        # 执行SQL并记录时间
        { time $ORACLE_HOME/bin/sqlplus -S $TEST_USER/$TEST_PASS <<EOF
SET TIMING ON
SET SERVEROUTPUT ON
$sql_statement
EXIT;
EOF
        ; } 2>> $test_file
        
        # 睡眠2秒
        sleep 2
    done
    
    log "完成测试: $test_name"
}

# 函数:执行基准测试
run_benchmark_tests() {
    log "开始执行基准测试..."
    
    # 测试1: 全表扫描
    run_sql_test "full_table_scan" "SELECT COUNT(*) FROM test_table;"
    
    # 测试2: 索引扫描
    run_sql_test "index_scan" "SELECT * FROM test_table WHERE created_date > SYSDATE - 100;"
    
    # 测试3: DML操作
    run_sql_test "dml_operations" "
DECLARE
    v_cnt NUMBER;
BEGIN
    -- 更新操作
    UPDATE test_table SET data = data || '_UPDATED' WHERE MOD(id, 10) = 0;
    COMMIT;
    
    -- 删除操作
    DELETE FROM test_table WHERE id > 990000;
    COMMIT;
    
    -- 插入操作
    FOR i IN 990001..1000000 LOOP
        INSERT INTO test_table VALUES (i, 'NEW TEST DATA ' || TO_CHAR(i), SYSDATE);
    END LOOP;
    COMMIT;
    
    -- 回滚测试
    SAVEPOINT sp1;
    UPDATE test_table SET data = data || '_TEMP' WHERE MOD(id, 5) = 0;
    ROLLBACK TO sp1;
    
    -- 统计行数
    SELECT COUNT(*) INTO v_cnt FROM test_table;
    DBMS_OUTPUT.PUT_LINE('总行数: ' || v_cnt);
END;
/
"
    
    log "基准测试完成"
}

# 函数:收集AWR报告
collect_awr_report() {
    log "收集AWR报告..."
    
    local snapshot_id_start=$($ORACLE_HOME/bin/sqlplus -S / as sysdba <<EOF
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SELECT MAX(snap_id) FROM dba_hist_snapshot;
EXIT;
EOF
)
    
    # 等待10分钟收集性能数据
    log "等待10分钟收集性能数据..."
    sleep 600
    
    local snapshot_id_end=$($ORACLE_HOME/bin/sqlplus -S / as sysdba <<EOF
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SELECT MAX(snap_id) FROM dba_hist_snapshot;
EXIT;
EOF
)
    
    local awr_file="$TEST_RESULTS_DIR/awr_report_$(date +%Y%m%d_%H%M%S).html"
    
    # 创建AWR报告
    $ORACLE_HOME/bin/sqlplus -S / as sysdba <<EOF
SET SERVEROUTPUT ON
SPOOL $awr_file
@?/rdbms/admin/awrrpt.sql html
$snapshot_id_start
$snapshot_id_end
7
SPOOL OFF
EXIT;
EOF
    
    log "AWR报告已生成: $awr_file"
}

# 主函数
case "$1" in
    run-tests)
        log "=== 开始性能测试 ==="
        run_benchmark_tests
        log "=== 性能测试完成 ==="
        ;;
    collect-awr)
        log "=== 开始收集AWR报告 ==="
        collect_awr_report
        log "=== AWR报告收集完成 ==="
        ;;
    *)
        echo "用法: $0 [run-tests|collect-awr]"
        echo "  run-tests     - 执行基准测试"
        echo "  collect-awr   - 收集AWR性能报告"
        exit 1
        ;;
esac    

(三)脚本setup-test-env.sh

#!/bin/bash

# Oracle大页内存性能测试 - 环境准备脚本

# 检查是否为root用户
if [ "$(id -u)" -ne 0 ]; then
    echo "请使用root用户执行此脚本"
    exit 1
fi

# 定义常量
SGA_SIZE_GB=8
HUGEPAGE_SIZE_MB=2
HUGEPAGE_COUNT=$((SGA_SIZE_GB * 1024 / HUGEPAGE_SIZE_MB))
ORACLE_SID="TESTDB"
ORACLE_HOME="/u01/app/oracle/product/19.3.0/dbhome_1"

# 函数:配置大页内存
configure_hugepages() {
    echo "配置大页内存..."
    # 修改sysctl.conf
    cat >> /etc/sysctl.conf <<EOF
# 配置大页内存用于Oracle性能测试
vm.nr_hugepages = $HUGEPAGE_COUNT
vm.transparent_hugepage.enabled = never
vm.transparent_hugepage.khugepaged = never
EOF
    
    # 使配置生效
    sysctl -p
    
    # 配置大页挂载点
    if ! grep -q "hugetlbfs" /etc/fstab; then
        echo "none /dev/hugepages hugetlbfs defaults 0 0" >> /etc/fstab
        mkdir -p /dev/hugepages
        mount -a
    fi
    
    echo "大页内存配置完成"
}

# 函数:禁用大页内存
disable_hugepages() {
    echo "禁用大页内存..."
    # 修改sysctl.conf
    sed -i '/vm.nr_hugepages/d' /etc/sysctl.conf
    sed -i '/vm.transparent_hugepage/d' /etc/sysctl.conf
    
    # 添加禁用配置
    cat >> /etc/sysctl.conf <<EOF
# 禁用大页内存
vm.nr_hugepages = 0
vm.transparent_hugepage.enabled = always
vm.transparent_hugepage.khugepaged = always
EOF
    
    # 使配置生效
    sysctl -p
    
    # 卸载大页挂载点
    if grep -q "hugetlbfs" /etc/fstab; then
        umount /dev/hugepages 2>/dev/null
        sed -i '/hugetlbfs/d' /etc/fstab
    fi
    
    echo "大页内存已禁用"
}

# 函数:配置Oracle使用大页
configure_oracle_hugepages() {
    echo "配置Oracle使用大页内存..."
    su - oracle -c "$ORACLE_HOME/bin/sqlplus / as sysdba <<EOF
ALTER SYSTEM SET sga_target=${SGA_SIZE_GB}G SCOPE=SPFILE;
ALTER SYSTEM SET use_large_pages=TRUE SCOPE=SPFILE;
EXIT;
EOF"
    
    echo "Oracle大页配置完成,请重启数据库使配置生效"
}

# 函数:配置Oracle不使用大页
configure_oracle_no_hugepages() {
    echo "配置Oracle不使用大页内存..."
    su - oracle -c "$ORACLE_HOME/bin/sqlplus / as sysdba <<EOF
ALTER SYSTEM SET sga_target=${SGA_SIZE_GB}G SCOPE=SPFILE;
ALTER SYSTEM SET use_large_pages=FALSE SCOPE=SPFILE;
EXIT;
EOF"
    
    echo "Oracle大页配置已禁用,请重启数据库使配置生效"
}

# 函数:创建测试用户和表
create_test_objects() {
    echo "创建测试用户和表..."
    su - oracle -c "$ORACLE_HOME/bin/sqlplus / as sysdba <<EOF
CREATE USER testuser IDENTIFIED BY testuser DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
GRANT CONNECT, RESOURCE, DBA TO testuser;
EXIT;
EOF"
    
    # 创建测试表
    su - oracle -c "$ORACLE_HOME/bin/sqlplus testuser/testuser <<EOF
CREATE TABLE test_table (
    id NUMBER PRIMARY KEY,
    data VARCHAR2(4000),
    created_date DATE
);

-- 插入100万条测试数据
BEGIN
    FOR i IN 1..1000000 LOOP
        INSERT INTO test_table VALUES (i, 'TEST DATA ' || TO_CHAR(i), SYSDATE);
        IF MOD(i, 10000) = 0 THEN
            COMMIT;
        END IF;
    END LOOP;
    COMMIT;
END;
/

-- 创建索引
CREATE INDEX idx_test_table ON test_table(created_date);
EXIT;
EOF"
    
    echo "测试对象创建完成"
}

# 主函数
case "$1" in
    enable-hugepages)
        configure_hugepages
        configure_oracle_hugepages
        ;;
    disable-hugepages)
        disable_hugepages
        configure_oracle_no_hugepages
        ;;
    create-test-data)
        create_test_objects
        ;;
    *)
        echo "用法: $0 [enable-hugepages|disable-hugepages|create-test-data]"
        echo "  enable-hugepages    - 配置并启用大页内存"
        echo "  disable-hugepages   - 禁用大页内存"
        echo "  create-test-data    - 创建测试数据"
        exit 1
        ;;
esac    

(四)使用说明test-procedure.md

# Oracle大页内存性能测试实验步骤

## 一、测试环境准备
### 1. 系统和数据库配置
确保测试环境满足以下条件:
- Linux操作系统(推荐Oracle Linux 7或Red Hat Enterprise Linux 7及以上版本)
- Oracle数据库(12c及以上版本)
- 足够的内存(建议至少16GB)
- 测试数据库实例
### 2. 安装测试脚本
将提供的三个脚本文件复制到测试服务器:
- setup-test-env.sh - 环境准备脚本
- run-performance-tests.sh - 测试执行脚本
- analyze-results.sh - 结果分析脚本

确保脚本具有执行权限:chmod +x setup-test-env.sh run-performance-tests.sh analyze-results.sh

## 二、执行测试
### 1. 禁用大页内存并进行测试
首先,以root用户执行以下命令禁用大页内存并配置Oracle不使用大页:./setup-test-env.sh disable-hugepages
重启系统使配置生效:shutdown -r now
系统重启后,以oracle用户连接数据库并启动数据库:sqlplus / as sysdba
STARTUP
创建测试数据:./setup-test-env.sh create-test-data
执行基准测试并收集结果:mkdir -p ~/non_hugepages_results
./run-performance-tests.sh run-tests > ~/non_hugepages_results/test_log_$(date +%Y%m%d).txt
./run-performance-tests.sh collect-awr > ~/non_hugepages_results/awr_log_$(date +%Y%m%d).txt
### 2. 启用大页内存并进行测试
以root用户执行以下命令启用大页内存并配置Oracle使用大页:./setup-test-env.sh enable-hugepages
重启系统使配置生效:shutdown -r now
系统重启后,以oracle用户连接数据库并启动数据库:sqlplus / as sysdba
STARTUP
执行基准测试并收集结果:mkdir -p ~/hugepages_results
./run-performance-tests.sh run-tests > ~/hugepages_results/test_log_$(date +%Y%m%d).txt
./run-performance-tests.sh collect-awr > ~/hugepages_results/awr_log_$(date +%Y%m%d).txt

## 三、分析测试结果
以oracle用户执行结果分析脚本:./analyze-results.sh ~/non_hugepages_results ~/hugepages_results
分析脚本会生成详细的测试对比结果和图表数据,查看结果文件:cat ~/hugepages_analysis_*/comparison_results.txt

## 四、实验结果解读
分析结果文件中的数据,重点关注以下指标:
1. 各项测试(全表扫描、索引扫描、DML操作)在启用大页和未启用大页情况下的执行时间对比
2. 性能提升百分比
3. AWR报告中的内存使用情况、CPU使用率等关键指标

通常情况下,启用大页内存后,Oracle数据库的性能会有明显提升,尤其是在内存访问密集型操作中。

## 五、注意事项
1. 在测试过程中,确保系统负载稳定,避免其他应用程序干扰测试结果
2. 测试前关闭所有不必要的服务和进程
3. 建议进行多次测试以确保结果的可靠性
4. 测试完成后,可以根据实际情况决定是否在生产环境中启用大页内存配置

这个实验设计通过对比启用和禁用大页内存两种情况下 Oracle 数据库的性能表现,能够直观地展示大页内存对数据库性能的影响。实验包含完整的环境准备、测试执行和结果分析流程,通过多种测试场景(全表扫描、索引扫描、DML 操作)验证大页内存的性能优势。

在执行实验时,请按照测试步骤说明依次操作,并根据实际环境调整相关参数(如 SGA 大小、测试数据量等)。测试完成后,通过分析结果文件中的性能数据和图表,你将能够清晰地看到启用大页内存后 Oracle 数据库的性能提升情况。

六、总结

通过以上步骤,我们完成了 Oracle 在 Linux 上的大页配置。合理配置大页内存能够有效提升 Oracle 数据库的性能和稳定性,但在配置过程中需要注意参数的准确设置,并根据实际环境进行适当调整。在实际应用中,还可以结合其他性能优化手段,进一步提升数据库的整体表现。​


🚀 更多数据库干货,欢迎关注【安呀智数据坊】

如果你觉得这篇文章对你有帮助,欢迎点赞 👍、收藏 ⭐ 和留言 💬 交流,让我知道你还想了解哪些数据库知识!

📬 想系统学习更多数据库实战案例与技术指南?

  • 📊 实战项目分享

  • 📚 技术原理讲解

  • 🧠 数据库架构思维

  • 🛠 工具推荐与实用技巧

立即关注,持续更新中 👇