Salin dan Bagikan
Optimasi InnoDB Buffer Pool di MySQL dan MariaDB: Konfigurasi untuk Performa Maksimal - Panduan lengkap optimasi InnoDB buffer pool di MySQL dan MariaDB dengan size calculation, multiple …

Optimasi InnoDB Buffer Pool di MySQL dan MariaDB: Konfigurasi untuk Performa Maksimal

Optimasi InnoDB Buffer Pool di MySQL dan MariaDB: Konfigurasi untuk Performa Maksimal

InnoDB buffer pool adalah komponen paling critical untuk performa database. Setelah mengoptimasi ratusan production servers, saya menyaksikan improvement dramatis dari konfigurasi yang tepat. Artikel ini akan membahas tuning buffer pool untuk throughput maksimal.

Mengapa Buffer Pool Penting?

Fungsi Buffer Pool

  • Cache data pages: Reduces disk I/O
  • Cache indexes: Faster query execution
  • Buffer changes: Delayed writes untuk performance
  • Adaptive hash index: In-memory hash untuk frequently accessed pages

Impact terhadap Performa

  • Buffer pool hit ratio: Target > 95%
  • Lower hit ratio: More disk I/O, slower queries
  • Properly sized: 80-90% data fits dalam memory

Sizing Buffer Pool

1. Calculate Optimal Size

-- Check current data size
SELECT 
    engine,
    ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_gb,
    ROUND(SUM(data_length) / 1024 / 1024 / 1024, 2) AS data_gb,
    ROUND(SUM(index_length) / 1024 / 1024 / 1024, 2) AS index_gb
FROM information_schema.tables
WHERE engine = 'InnoDB'
GROUP BY engine;

-- Check buffer pool status
SHOW STATUS LIKE 'Innodb_buffer_pool%';

2. Memory Calculation

Rules:

  • Dedicate 70-80% RAM untuk InnoDB buffer pool
  • Leave 20-30% untuk OS, connections, dan other processes
  • Maximum 64GB per instance (gunakan multiple instances untuk lebih besar)

Contoh Perhitungan:

Server dengan 16GB RAM:
- Buffer Pool: 12GB (75%)
- OS dan lainnya: 4GB (25%)

Server dengan 32GB RAM:
- Buffer Pool: 24GB (75%)
- OS dan lainnya: 8GB (25%)

Server dengan 64GB RAM:
- Buffer Pool: 48GB (75%) 
  atau 2 instances x 24GB
- OS dan lainnya: 16GB (25%)

3. Configuration

# my.cnf
[mysqld]
# Buffer pool size (contoh untuk server 16GB)
innodb_buffer_pool_size = 12G

# Untuk server 32GB
innodb_buffer_pool_size = 24G

# Untuk server 64GB dengan multiple instances
innodb_buffer_pool_size = 48G
innodb_buffer_pool_instances = 4  # 48GB / 4 = 12GB per instance

Buffer Pool Instances

1. Kapan Menggunakan Multiple Instances?

Gunakan multiple instances jika:

  • Buffer pool size > 1GB
  • Server memiliki multiple CPU cores
  • High concurrency workload

Rules:

innodb_buffer_pool_instances = innodb_buffer_pool_size / 1GB
Maximum: 64 instances
Minimum: 1 instance

2. Configuration

[mysqld]
# Single instance (untuk < 1GB)
innodb_buffer_pool_size = 512M
innodb_buffer_pool_instances = 1

# Multiple instances
innodb_buffer_pool_size = 16G
innodb_buffer_pool_instances = 16

# Large server
innodb_buffer_pool_size = 128G
innodb_buffer_pool_instances = 64  # Maximum

3. Monitoring Instance Performance

-- Check instance usage
SELECT 
    POOL_ID,
    POOL_SIZE,
    FREE_BUFFERS,
    DATABASE_PAGES,
    OLD_DATABASE_PAGES,
    PAGES_MADE_YOUNG,
    PAGES_NOT_MADE_YOUNG
FROM information_schema.INNODB_BUFFER_POOL_STATS;

Buffer Pool Page Management

1. Page Size Configuration

[mysqld]
# Default 16KB (jangan ubah kecuali ada specific reason)
innodb_page_size = 16384

# Alternative: 8KB, 4KB, 32KB, 64KB (MySQL 5.7+)
# Tapi hanya bisa set saat inisialisasi pertama!

2. Old Blocks dan LRU Algorithm

[mysqld]
# Percentage untuk "old" blocks sublist
innodb_old_blocks_pct = 37  # Default: 37%

# Time threshold untuk move ke new sublist
innodb_old_blocks_time = 1000  # Default: 1000ms

3. Midpoint Insertion Strategy

-- Check LRU stats
SHOW ENGINE INNODB STATUS\G

-- Look for:
-- Buffer pool hit rate: 1000 / 1000
-- Youngs/s non-youngs/s: untuk page movement rate

Read-Ahead Optimization

1. Linear Read-Ahead

[mysqld]
# Enable linear read-ahead
innodb_read_ahead_threshold = 56  # Default: 56 (pages)

# Jika 56 consecutive pages dari extent di-access,
# InnoDB mem-read seluruh extent berikutnya

2. Random Read-Ahead

[mysqld]
# Enable random read-ahead (buffered dalam memory)
innodb_random_read_ahead = ON  # Default: OFF

# Hanya useful untuk specific workloads

Write Performance Optimization

1. Change Buffering

[mysqld]
# Enable change buffering untuk secondary index changes
innodb_change_buffering = all  # Default: all

# Options: inserts, deletes, purges, changes, none

# Maximum size untuk change buffer (percentage dari buffer pool)
innodb_change_buffer_max_size = 25  # Default: 25%

2. Doublewrite Buffer

[mysqld]
# Enable doublewrite (safety untuk crash recovery)
innodb_doublewrite = ON  # Default: ON

# Untuk SSD dengan power protection, bisa disable
# Tapi NOT RECOMMENDED untuk production!

3. Flush Configuration

[mysqld]
# Commit behavior
innodb_flush_log_at_trx_commit = 1  # ACID compliant, sync every commit
# Alternatives:
# 0: Write ke log setiap detik (fastest, least safe)
# 1: Sync setiap commit (safest)
# 2: Write ke OS cache setiap commit, sync setiap detik (balance)

# Buffer pool flush behavior
innodb_flush_method = O_DIRECT  # Bypass OS cache untuk data files
# Options: fsync, O_DSYNC, littlesync, nosync, O_DIRECT

# Dirty pages percentage untuk trigger flush
innodb_max_dirty_pages_pct = 75  # Default: 75%
innodb_max_dirty_pages_pct_lwm = 10  # Low water mark: 10%

Monitoring Buffer Pool Performance

1. Hit Ratio Calculation

-- Calculate hit ratio
SELECT 
    ROUND(
        (SELECT SUM_VALUE FROM performance_schema.global_status 
         WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') /
        ((SELECT SUM_VALUE FROM performance_schema.global_status 
          WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') +
         (SELECT SUM_VALUE FROM performance_schema.global_status 
          WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads'))
        * 100, 
        2
    ) AS hit_ratio_percent;

-- Alternative (simpler)
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
-- Hit Ratio = 1 - (reads / read_requests)

2. Detailed Buffer Pool Statistics

-- Comprehensive buffer pool stats
SELECT 
    POOL_ID,
    POOL_SIZE,
    FREE_BUFFERS,
    DATABASE_PAGES,
    OLD_DATABASE_PAGES,
    ROUND((DATABASE_PAGES / POOL_SIZE) * 100, 2) AS pool_utilization_pct,
    PAGES_MADE_YOUNG,
    PAGES_NOT_MADE_YOUNG,
    NUMBER_PAGES_READ,
    NUMBER_PAGES_CREATED,
    NUMBER_PAGES_WRITTEN,
    PAGES_READ_RATE,
    PAGES_CREATE_RATE,
    PAGES_WRITTEN_RATE
FROM information_schema.INNODB_BUFFER_POOL_STATS;

3. Real-time Monitoring Script

sudo nano /usr/local/bin/monitor_buffer_pool.sh
#!/bin/bash

LOG_FILE="/var/log/buffer_pool_monitor.log"

# Get metrics
HIT_RATIO=$(mysql -e "
SELECT ROUND(
    (1 - (SUM(CASE WHEN VARIABLE_NAME = 'Innodb_buffer_pool_reads' THEN VARIABLE_VALUE END) / 
          SUM(CASE WHEN VARIABLE_NAME = 'Innodb_buffer_pool_read_requests' THEN VARIABLE_VALUE END))) * 100,
    2
) as hit_ratio
FROM performance_schema.global_status
WHERE VARIABLE_NAME IN ('Innodb_buffer_pool_reads', 'Innodb_buffer_pool_read_requests');
" | tail -1)

DIRTY_PAGES=$(mysql -e "SHOW STATUS LIKE 'Innodb_buffer_pool_pages_dirty';" | awk 'NR==2{print $2}')
TOTAL_PAGES=$(mysql -e "SHOW STATUS LIKE 'Innodb_buffer_pool_pages_total';" | awk 'NR==2{print $2}')
DIRTY_PCT=$(echo "scale=2; $DIRTY_PAGES / $TOTAL_PAGES * 100" | bc)

echo "[$(date)] Hit Ratio: ${HIT_RATIO}% | Dirty Pages: ${DIRTY_PCT}%" >> $LOG_FILE

# Alert jika hit ratio rendah
if (( $(echo "$HIT_RATIO < 95" | bc -l) )); then
    echo "ALERT: Buffer pool hit ratio low: ${HIT_RATIO}%" | \
        mail -s "[WARNING] MySQL Buffer Pool Performance" admin@example.com
fi

Resizing Buffer Pool Online (MySQL 5.7+ / MariaDB 10.2+)

1. Increase Buffer Pool Size

-- Resize tanpa restart (jika decrease)
SET GLOBAL innodb_buffer_pool_size = 16 * 1024 * 1024 * 1024;  -- 16GB

-- Increase bisa dilakukan online di MySQL 5.7+
-- Tapi akan meng-lock operations sementara

2. Monitor Resize Progress

-- Check resize status
SHOW STATUS LIKE 'Innodb_buffer_pool_resize%';

-- InnoDB_buffer_pool_resize_status: Completed, Resizing, atau error

Common Issues dan Solusi

1. Low Hit Ratio (< 90%)

Causes:

  • Buffer pool too small
  • Working set larger than buffer pool
  • Full table scans

Solusi:

-- Check largest tables
SELECT 
    table_name,
    ROUND((data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM information_schema.tables
WHERE engine = 'InnoDB'
ORDER BY (data_length + index_length) DESC
LIMIT 10;

-- Increase buffer pool size
SET GLOBAL innodb_buffer_pool_size = <larger_value>;

-- Check untuk full table scans
EXPLAIN SELECT * FROM large_table WHERE non_indexed_column = 'value';

2. High Buffer Pool Pages Flushed

Causes:

  • Too many dirty pages
  • Write-heavy workload
  • Insufficient flush capacity

Solusi:

# Increase write capacity
innodb_io_capacity = 2000  # IOPS dari storage
innodb_io_capacity_max = 4000

# Increase flush threads
innodb_page_cleaners = 8  # Default: 4

3. Buffer Pool Contentment Issues

-- Check untuk contended pages
SELECT 
    OBJECT_SCHEMA,
    OBJECT_NAME,
    COUNT_READ,
    COUNT_WRITE,
    SUM_TIMER_WAIT
FROM performance_schema.table_io_waits_summary_by_table
ORDER BY SUM_TIMER_WAIT DESC;

-- Hot pages mungkin perlu caching di application layer

Best Practices

  1. Size untuk working set: 70-80% dari frequently accessed data
  2. Use multiple instances: Untuk buffer pool > 1GB
  3. Monitor hit ratio: Target > 95%
  4. SSD optimization: Adjust innodb_io_capacity
  5. Regular analysis: Perfomance degrades over time
  6. Test changes: Benchmark sebelum production
  7. Document: Track configuration changes

Configuration Summary

# Recommended configuration untuk production
[mysqld]
# Buffer Pool
innodb_buffer_pool_size = 24G  # 75% dari RAM
innodb_buffer_pool_instances = 24  # 1 per GB, max 64

# Page Management
innodb_old_blocks_pct = 37
innodb_old_blocks_time = 1000

# Read Performance
innodb_read_ahead_threshold = 56
innodb_random_read_ahead = OFF

# Write Performance
innodb_change_buffering = all
innodb_change_buffer_max_size = 25
innodb_doublewrite = ON

# Flush Performance
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_max_dirty_pages_pct = 75
innodb_page_cleaners = 8

Kesimpulan

Optimasi buffer pool adalah foundational untuk performa InnoDB:

  • Proper sizing mengurangi disk I/O
  • Multiple instances improve concurrency
  • Monitoring memastikan optimal performance
  • Regular tuning menjaga efficiency

Dengan konfigurasi yang tepat, Anda akan melihat improvement signifikan dalam query response times dan throughput.

Artikel Terkait

Link Postingan : https://www.tirinfo.com/optimasi-innodb-buffer-pool-mysql-mariadb-performa-maksimal/

Hendra WIjaya
Tirinfo
6 minutes.
3 February 2026