Learn to benchmark MySQL and PostgreSQL database performance using sysbench 1.0.20 combined with fio 3.37 disk I/O testing. This comprehensive guide covers installation, configuration, execution of performance tests, and analysis of results for database optimization in production environments.
Prerequisites
- Root or sudo access
- 8GB+ RAM recommended
- 10GB+ free disk space
- Database server installation
What this solves
Database performance bottlenecks can severely impact application response times and user experience. This tutorial shows you how to use sysbench 1.0.20 and fio 3.37 together to benchmark both database workloads and underlying storage performance. You'll learn to identify whether performance issues stem from database configuration, disk I/O limitations, or system resource constraints, enabling data-driven optimization decisions for MySQL and PostgreSQL deployments.
Step-by-step installation
Update system packages
Start by updating your package manager to ensure you get the latest versions of dependencies.
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget build-essential git
Install fio for disk I/O benchmarking
Install fio 3.37 from repositories or compile from source for the latest features.
sudo apt install -y fio
fio --version
Install sysbench dependencies
Install required libraries for compiling sysbench with MySQL and PostgreSQL support.
sudo apt install -y libmysqlclient-dev libpq-dev libaio-dev pkg-config autotools-dev autoconf automake libtool
Compile and install sysbench 1.0.20
Download and compile sysbench from source to get version 1.0.20 with all database drivers.
cd /tmp
wget https://github.com/akopytov/sysbench/archive/1.0.20.tar.gz
tar -xzf 1.0.20.tar.gz
cd sysbench-1.0.20
./autogen.sh
./configure --with-mysql --with-pgsql
make -j$(nproc)
sudo make install
sudo ldconfig
Verify sysbench installation
Check that sysbench is installed correctly with database support enabled.
sysbench --version
sysbench --help | grep -E "mysql|pgsql"
Install database systems for testing
Install MySQL and PostgreSQL servers for benchmarking. Skip if you're testing existing databases.
sudo apt install -y mysql-server postgresql postgresql-contrib
sudo systemctl enable --now mysql postgresql
Configure test databases
Configure MySQL test database
Create a dedicated database and user for sysbench testing with proper permissions.
sudo mysql -e "CREATE DATABASE sysbenchdb;"
sudo mysql -e "CREATE USER 'sysbench'@'localhost' IDENTIFIED BY 'StrongPassword123!';"
sudo mysql -e "GRANT ALL PRIVILEGES ON sysbenchdb.* TO 'sysbench'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
Configure PostgreSQL test database
Set up PostgreSQL database and user for sysbench testing.
sudo -u postgres createdb sysbenchdb
sudo -u postgres psql -c "CREATE USER sysbench WITH PASSWORD 'StrongPassword123!';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE sysbenchdb TO sysbench;"
sudo -u postgres psql -c "ALTER USER sysbench CREATEDB;"
Configure PostgreSQL authentication
Update pg_hba.conf to allow password authentication for the sysbench user.
# Add this line before other local entries
local sysbenchdb sysbench md5
sudo systemctl reload postgresql
Execute I/O performance benchmarks
Create directory for test data
Create a dedicated directory for benchmark data files with proper permissions.
sudo mkdir -p /var/lib/benchmark-data
sudo chown $(whoami):$(whoami) /var/lib/benchmark-data
cd /var/lib/benchmark-data
Run sequential read/write tests
Test sequential I/O performance to establish baseline storage throughput.
# Sequential write test
fio --name=seq-write --ioengine=libaio --iodepth=32 --rw=write --bs=64k --direct=1 --size=4G --numjobs=1 --runtime=300 --group_reporting --filename=/var/lib/benchmark-data/test-seq-write
Sequential read test
fio --name=seq-read --ioengine=libaio --iodepth=32 --rw=read --bs=64k --direct=1 --size=4G --numjobs=1 --runtime=300 --group_reporting --filename=/var/lib/benchmark-data/test-seq-read
Run random I/O tests
Test random I/O patterns that simulate database workloads more accurately.
# Random write IOPS test
fio --name=rand-write --ioengine=libaio --iodepth=16 --rw=randwrite --bs=4k --direct=1 --size=2G --numjobs=4 --runtime=300 --group_reporting --filename=/var/lib/benchmark-data/test-rand-write
Random read IOPS test
fio --name=rand-read --ioengine=libaio --iodepth=16 --rw=randread --bs=4k --direct=1 --size=2G --numjobs=4 --runtime=300 --group_reporting --filename=/var/lib/benchmark-data/test-rand-read
Run mixed workload test
Simulate realistic database I/O patterns with mixed read/write operations.
fio --name=mixed-rw --ioengine=libaio --iodepth=16 --rw=randrw --rwmixread=70 --bs=8k --direct=1 --size=2G --numjobs=4 --runtime=600 --group_reporting --filename=/var/lib/benchmark-data/test-mixed-rw
Execute database performance benchmarks
Prepare MySQL test data
Create test tables and populate with data for sysbench OLTP workloads.
sysbench oltp_read_write --table-size=1000000 --tables=8 --mysql-db=sysbenchdb --mysql-user=sysbench --mysql-password=StrongPassword123! --mysql-host=localhost prepare
Run MySQL OLTP benchmark
Execute comprehensive OLTP workload test against MySQL with various thread counts.
# Run with increasing thread counts
for threads in 1 4 8 16 32; do
echo "Testing MySQL with $threads threads"
sysbench oltp_read_write --table-size=1000000 --tables=8 --threads=$threads --time=300 --mysql-db=sysbenchdb --mysql-user=sysbench --mysql-password=StrongPassword123! --mysql-host=localhost run > mysql_benchmark_${threads}t.txt
sleep 30
done
Run MySQL read-only benchmark
Test read-heavy workloads to measure query performance and caching effectiveness.
sysbench oltp_read_only --table-size=1000000 --tables=8 --threads=16 --time=300 --mysql-db=sysbenchdb --mysql-user=sysbench --mysql-password=StrongPassword123! --mysql-host=localhost run > mysql_readonly_benchmark.txt
Prepare PostgreSQL test data
Set up PostgreSQL test environment with the same data structure.
sysbench oltp_read_write --table-size=1000000 --tables=8 --pgsql-db=sysbenchdb --pgsql-user=sysbench --pgsql-password=StrongPassword123! --pgsql-host=localhost prepare
Run PostgreSQL OLTP benchmark
Execute the same workload against PostgreSQL for comparison.
for threads in 1 4 8 16 32; do
echo "Testing PostgreSQL with $threads threads"
sysbench oltp_read_write --table-size=1000000 --tables=8 --threads=$threads --time=300 --pgsql-db=sysbenchdb --pgsql-user=sysbench --pgsql-password=StrongPassword123! --pgsql-host=localhost run > pgsql_benchmark_${threads}t.txt
sleep 30
done
Advanced benchmark scenarios
Memory performance test
Test memory allocation and access patterns to identify memory bottlenecks.
sysbench memory --memory-block-size=1M --memory-total-size=10G --threads=4 run > memory_benchmark.txt
CPU performance test
Benchmark CPU performance to establish system computational capacity.
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) run > cpu_benchmark.txt
Custom Lua script benchmark
Create custom workload patterns using sysbench Lua scripting capabilities.
#!/usr/bin/env sysbench
function thread_init()
drv = sysbench.sql.driver()
con = drv:connect()
end
function event()
local table_id = sysbench.rand.uniform(1, sysbench.opt.tables)
local id = sysbench.rand.uniform(1, sysbench.opt.table_size)
con:query("SELECT c FROM sbtest" .. table_id .. " WHERE id=" .. id)
con:query("SELECT c FROM sbtest" .. table_id .. " WHERE id BETWEEN " .. id .. " AND " .. (id + 100))
con:query("UPDATE sbtest" .. table_id .. " SET k=k+1 WHERE id=" .. id)
end
function thread_done()
con:disconnect()
end
sysbench /var/lib/benchmark-data/custom_workload.lua --table-size=1000000 --tables=8 --threads=16 --time=300 --mysql-db=sysbenchdb --mysql-user=sysbench --mysql-password=StrongPassword123! --mysql-host=localhost run > custom_workload_benchmark.txt
Analyze performance metrics
Extract key I/O metrics
Parse fio results to extract important performance indicators.
# Create analysis script
cat > analyze_fio.sh << 'EOF'
#!/bin/bash
echo "=== Disk I/O Performance Summary ==="
echo "Sequential Write Throughput:"
grep -A 5 "WRITE:" fio_seq_write.log | grep "bw="
echo "Sequential Read Throughput:"
grep -A 5 "READ:" fio_seq_read.log | grep "bw="
echo "Random Write IOPS:"
grep -A 5 "WRITE:" fio_rand_write.log | grep "iops="
echo "Random Read IOPS:"
grep -A 5 "READ:" fio_rand_read.log | grep "iops="
EOF
chmod +x analyze_fio.sh
Extract database performance metrics
Parse sysbench results to compare database performance across configurations.
cat > analyze_db.sh << 'EOF'
#!/bin/bash
echo "=== Database Performance Summary ==="
for file in mysql_benchmark_*.txt; do
threads=$(echo $file | grep -o '[0-9]*t' | tr -d 't')
tps=$(grep "transactions:" $file | awk '{print $3}' | tr -d '(')
latency=$(grep "95th percentile:" $file | awk '{print $3}')
echo "MySQL $threads threads: $tps TPS, 95th percentile: $latency ms"
done
for file in pgsql_benchmark_*.txt; do
threads=$(echo $file | grep -o '[0-9]*t' | tr -d 't')
tps=$(grep "transactions:" $file | awk '{print $3}' | tr -d '(')
latency=$(grep "95th percentile:" $file | awk '{print $3}')
echo "PostgreSQL $threads threads: $tps TPS, 95th percentile: $latency ms"
done
EOF
chmod +x analyze_db.sh
./analyze_db.sh
Generate comprehensive report
Create detailed performance report combining I/O and database metrics.
cat > generate_report.sh << 'EOF'
#!/bin/bash
REPORT_FILE="performance_report_$(date +%Y%m%d_%H%M%S).txt"
echo "Database Performance Benchmark Report" > $REPORT_FILE
echo "Generated on: $(date)" >> $REPORT_FILE
echo "========================================" >> $REPORT_FILE
echo "" >> $REPORT_FILE
echo "System Information:" >> $REPORT_FILE
echo "CPU: $(lscpu | grep 'Model name' | awk -F: '{print $2}' | sed 's/^[ \t]*//')" >> $REPORT_FILE
echo "Memory: $(free -h | grep '^Mem:' | awk '{print $2}')" >> $REPORT_FILE
echo "Storage: $(df -h / | tail -1 | awk '{print $2, $4}')" >> $REPORT_FILE
echo "" >> $REPORT_FILE
./analyze_fio.sh >> $REPORT_FILE 2>/dev/null || echo "FIO results not available" >> $REPORT_FILE
echo "" >> $REPORT_FILE
./analyze_db.sh >> $REPORT_FILE
echo "Report saved to: $REPORT_FILE"
EOF
chmod +x generate_report.sh
./generate_report.sh
Optimize based on results
Identify performance bottlenecks
Compare results to identify whether limitations are I/O, CPU, memory, or database configuration related.
# Check I/O wait time during benchmarks
iostat -x 1 5
Monitor memory usage patterns
free -h
cat /proc/meminfo | grep -E "MemAvailable|Buffers|Cached"
Check database-specific metrics
mysqladmin -u sysbench -pStrongPassword123! extended-status | grep -E "Innodb_buffer_pool|Query_cache"
psql -U sysbench -d sysbenchdb -c "SELECT * FROM pg_stat_database WHERE datname='sysbenchdb';"
Apply MySQL optimizations
Configure MySQL parameters based on benchmark findings. This configuration works for systems with 8GB+ RAM.
[mysqld]
Buffer pool size (70-80% of available RAM)
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
I/O optimizations
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_io_capacity = 1000
innodb_io_capacity_max = 2000
Connection and thread settings
max_connections = 200
thread_cache_size = 50
table_open_cache = 4000
Query cache (if read-heavy workload)
query_cache_type = 1
query_cache_size = 256M
Binary logging for replication
log_bin = /var/log/mysql/mysql-bin.log
binlog_cache_size = 1M
max_binlog_cache_size = 128M
sudo systemctl restart mysql
Apply PostgreSQL optimizations
Configure PostgreSQL for better performance based on benchmark results.
# Memory settings
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 64MB
maintenance_work_mem = 512MB
Checkpoint and WAL settings
wal_buffers = 64MB
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min
max_wal_size = 4GB
min_wal_size = 1GB
Connection settings
max_connections = 200
Query planner
random_page_cost = 1.1
effective_io_concurrency = 200
Logging for analysis
log_min_duration_statement = 1000
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
sudo systemctl restart postgresql
Verify your setup
# Verify tool installations
sysbench --version
fio --version
Test database connections
mysql -u sysbench -pStrongPassword123! -e "SELECT COUNT(*) FROM sysbenchdb.sbtest1;"
psql -U sysbench -d sysbenchdb -c "SELECT COUNT(*) FROM sbtest1;"
Check available benchmark scripts
sysbench --test=help
ls -la /usr/local/share/sysbench/
Verify system resources
df -h /var/lib/benchmark-data
free -h
nproc
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| sysbench compilation fails | Missing development headers | Install libmysqlclient-dev libpq-dev libaio-dev |
| Database connection refused | Authentication configuration | Check user permissions and pg_hba.conf settings |
| fio tests show very low IOPS | Testing on slow storage or VM | Use --direct=1 and test on dedicated storage |
| Inconsistent benchmark results | Background processes interfering | Run during low activity periods and disable unnecessary services |
| Out of space during tests | Insufficient disk space | Use smaller test files or clean /var/lib/benchmark-data |
| High memory usage during tests | Large buffer pools or test data | Reduce table_size or adjust database buffer settings |
Next steps
- Monitor MySQL performance with Prometheus and Grafana for ongoing performance tracking
- Configure MySQL binary log backup and point-in-time recovery for production reliability
- Monitor PostgreSQL performance with Prometheus and Grafana for comprehensive database monitoring
- Set up database performance alerting with Prometheus and Grafana for proactive monitoring
- Optimize database connection pooling for high availability applications
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default configuration
MYSQL_PASSWORD="${MYSQL_PASSWORD:-StrongPassword123!}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-StrongPassword123!}"
BENCHMARK_DIR="/var/lib/benchmark-data"
SYSBENCH_VERSION="1.0.20"
print_usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --mysql-password PASS Set MySQL password (default: StrongPassword123!)"
echo " --postgres-password PASS Set PostgreSQL password (default: StrongPassword123!)"
echo " --benchmark-dir DIR Set benchmark directory (default: /var/lib/benchmark-data)"
echo " -h, --help Show this help message"
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
cleanup() {
log_error "Installation failed. Cleaning up..."
rm -rf /tmp/sysbench-${SYSBENCH_VERSION}* || true
exit 1
}
trap cleanup ERR
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--mysql-password)
MYSQL_PASSWORD="$2"
shift 2
;;
--postgres-password)
POSTGRES_PASSWORD="$2"
shift 2
;;
--benchmark-dir)
BENCHMARK_DIR="$2"
shift 2
;;
-h|--help)
print_usage
exit 0
;;
*)
log_error "Unknown option: $1"
print_usage
exit 1
;;
esac
done
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root or with sudo"
exit 1
fi
# Detect distribution and set package manager
if [[ ! -f /etc/os-release ]]; then
log_error "/etc/os-release not found. Cannot detect distribution."
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
MYSQL_DEV_PKG="libmysqlclient-dev"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
MYSQL_DEV_PKG="mysql-devel"
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
MYSQL_DEV_PKG="mysql-devel"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
MYSQL_DEV_PKG="mysql-devel"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
log_info "Detected distribution: $PRETTY_NAME"
log_info "Using package manager: $PKG_MGR"
# Step 1: Update system packages
echo -e "\n${GREEN}[1/8] Updating system packages...${NC}"
$PKG_UPDATE
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL curl wget build-essential git pkg-config autotools-dev autoconf automake libtool
elif [[ "$PKG_MGR" == "dnf" ]]; then
dnf groupinstall -y "Development Tools"
$PKG_INSTALL curl wget git pkgconfig autotools automake libtool
elif [[ "$PKG_MGR" == "yum" ]]; then
yum groupinstall -y "Development Tools"
$PKG_INSTALL curl wget git pkgconfig autotools automake libtool
fi
# Step 2: Install fio
echo -e "\n${GREEN}[2/8] Installing fio for disk I/O benchmarking...${NC}"
$PKG_INSTALL fio
fio --version
# Step 3: Install sysbench dependencies
echo -e "\n${GREEN}[3/8] Installing sysbench dependencies...${NC}"
$PKG_INSTALL $MYSQL_DEV_PKG postgresql-devel libaio-devel
# Step 4: Compile and install sysbench
echo -e "\n${GREEN}[4/8] Compiling and installing sysbench ${SYSBENCH_VERSION}...${NC}"
cd /tmp
wget -q https://github.com/akopytov/sysbench/archive/${SYSBENCH_VERSION}.tar.gz
tar -xzf ${SYSBENCH_VERSION}.tar.gz
cd sysbench-${SYSBENCH_VERSION}
./autogen.sh
./configure --with-mysql --with-pgsql
make -j$(nproc)
make install
ldconfig
# Step 5: Verify sysbench installation
echo -e "\n${GREEN}[5/8] Verifying sysbench installation...${NC}"
sysbench --version
log_info "Checking database support:"
sysbench --help | grep -E "mysql|pgsql" || log_warn "Database support check completed"
# Step 6: Install database systems
echo -e "\n${GREEN}[6/8] Installing database systems...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL mysql-server postgresql postgresql-contrib
systemctl enable --now mysql postgresql
elif [[ "$PKG_MGR" == "dnf" || "$PKG_MGR" == "yum" ]]; then
$PKG_INSTALL mysql-server postgresql-server postgresql-contrib
systemctl enable --now mysqld postgresql
if [[ ! -f /var/lib/pgsql/data/postgresql.conf ]]; then
postgresql-setup --initdb
fi
fi
# Wait for services to start
sleep 5
# Step 7: Configure databases
echo -e "\n${GREEN}[7/8] Configuring test databases...${NC}"
# Configure MySQL
log_info "Configuring MySQL test database..."
mysql -e "CREATE DATABASE IF NOT EXISTS sysbenchdb;" || true
mysql -e "CREATE USER IF NOT EXISTS 'sysbench'@'localhost' IDENTIFIED BY '${MYSQL_PASSWORD}';" || true
mysql -e "GRANT ALL PRIVILEGES ON sysbenchdb.* TO 'sysbench'@'localhost';" || true
mysql -e "FLUSH PRIVILEGES;" || true
# Configure PostgreSQL
log_info "Configuring PostgreSQL test database..."
sudo -u postgres createdb sysbenchdb 2>/dev/null || log_warn "PostgreSQL database may already exist"
sudo -u postgres psql -c "CREATE USER sysbench WITH PASSWORD '${POSTGRES_PASSWORD}';" 2>/dev/null || log_warn "PostgreSQL user may already exist"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE sysbenchdb TO sysbench;" || true
sudo -u postgres psql -c "ALTER USER sysbench CREATEDB;" || true
# Configure PostgreSQL authentication
PG_HBA_CONF="/var/lib/pgsql/data/pg_hba.conf"
if [[ "$PKG_MGR" == "apt" ]]; then
PG_VERSION=$(pg_config --version | sed 's/^PostgreSQL \([0-9]\+\).*/\1/')
PG_HBA_CONF="/etc/postgresql/${PG_VERSION}/main/pg_hba.conf"
fi
if [[ -f "$PG_HBA_CONF" ]]; then
if ! grep -q "local.*sysbenchdb.*sysbench.*md5" "$PG_HBA_CONF"; then
sed -i '/^local.*all.*all.*peer/i local sysbenchdb sysbench md5' "$PG_HBA_CONF"
systemctl reload postgresql
fi
fi
# Step 8: Create benchmark directory and verify installation
echo -e "\n${GREEN}[8/8] Creating benchmark directory and verifying installation...${NC}"
mkdir -p "$BENCHMARK_DIR"
chown root:root "$BENCHMARK_DIR"
chmod 755 "$BENCHMARK_DIR"
# Verification checks
log_info "Running verification checks..."
echo "✓ fio version: $(fio --version)"
echo "✓ sysbench version: $(sysbench --version)"
echo "✓ MySQL service: $(systemctl is-active mysqld mysql 2>/dev/null | head -1)"
echo "✓ PostgreSQL service: $(systemctl is-active postgresql)"
echo "✓ Benchmark directory: $BENCHMARK_DIR ($(ls -ld $BENCHMARK_DIR | cut -d' ' -f1,3,4))"
log_info "Installation completed successfully!"
log_info "MySQL credentials: user=sysbench, password=$MYSQL_PASSWORD, database=sysbenchdb"
log_info "PostgreSQL credentials: user=sysbench, password=$POSTGRES_PASSWORD, database=sysbenchdb"
log_info "Benchmark directory: $BENCHMARK_DIR"
Review the script before running. Execute with: bash install.sh