Learn advanced MariaDB performance optimization techniques including query profiling, slow query analysis, and strategic indexing for high-traffic applications. This tutorial covers query execution plan analysis, covering indexes, and automated monitoring setup.
Prerequisites
- MariaDB 11.6 installed and running
- Root or sudo access
- Basic SQL knowledge
- At least 4GB RAM available
What this solves
High-traffic applications often experience database bottlenecks that manifest as slow page loads, timeouts, and poor user experience. This tutorial teaches you advanced MariaDB 11.6 performance optimization techniques including query profiling with Performance Schema, strategic indexing with covering indexes, and automated slow query monitoring to handle thousands of concurrent users effectively.
Step-by-step configuration
Enable Performance Schema and query logging
Configure MariaDB to collect detailed query performance metrics and enable slow query logging for analysis.
[mysqld]
Performance Schema configuration
performance_schema = ON
performance_schema_consumer_events_statements_current = ON
performance_schema_consumer_events_statements_history = ON
performance_schema_consumer_events_statements_history_long = ON
Slow query log configuration
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_slow_slave_statements = 1
Query cache optimization
query_cache_type = 1
query_cache_size = 268435456
query_cache_limit = 2097152
Connection and buffer optimizations
max_connections = 500
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 512M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
Restart MariaDB to apply configuration
Restart the service to enable Performance Schema and slow query logging.
sudo systemctl restart mariadb
sudo systemctl status mariadb
Create sample high-traffic database schema
Set up a realistic e-commerce database schema to demonstrate optimization techniques.
sudo mysql -u root -p
CREATE DATABASE ecommerce_db;
USE ecommerce_db;
CREATE TABLE users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL,
status ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
INDEX idx_email (email),
INDEX idx_status_created (status, created_at)
);
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
category_id INT NOT NULL,
price DECIMAL(10,2) NOT NULL,
stock_quantity INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category_price (category_id, price),
INDEX idx_stock (stock_quantity),
INDEX idx_name (name)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
total_amount DECIMAL(10,2) NOT NULL,
order_status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id),
INDEX idx_user_status (user_id, order_status),
INDEX idx_status_date (order_status, created_at),
INDEX idx_created_at (created_at)
);
CREATE TABLE order_items (
item_id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id),
INDEX idx_order_product (order_id, product_id),
INDEX idx_product_id (product_id)
);
Generate sample data for testing
Insert realistic test data to simulate high-traffic conditions and analyze query performance.
# Insert sample users
INSERT INTO users (username, email, status) VALUES
('john_doe', 'john@example.com', 'active'),
('jane_smith', 'jane@example.com', 'active'),
('bob_wilson', 'bob@example.com', 'inactive');
Insert sample products
INSERT INTO products (name, category_id, price, stock_quantity) VALUES
('Gaming Laptop', 1, 1299.99, 50),
('Wireless Mouse', 1, 29.99, 200),
('Mechanical Keyboard', 1, 149.99, 75),
('4K Monitor', 1, 399.99, 30),
('USB-C Hub', 1, 79.99, 100);
Insert sample orders
INSERT INTO orders (user_id, total_amount, order_status) VALUES
(1, 1329.98, 'delivered'),
(2, 229.98, 'processing'),
(1, 79.99, 'shipped'),
(3, 449.98, 'pending');
Insert order items
INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES
(1, 1, 1, 1299.99),
(1, 2, 1, 29.99),
(2, 3, 1, 149.99),
(2, 2, 1, 29.99),
(2, 1, 1, 1299.99),
(3, 5, 1, 79.99),
(4, 4, 1, 399.99),
(4, 1, 1, 1299.99);
Analyze query performance with EXPLAIN
Use EXPLAIN to understand query execution plans and identify optimization opportunities.
# Analyze a complex join query
EXPLAIN EXTENDED
SELECT u.username, u.email, o.order_id, o.total_amount, p.name, oi.quantity
FROM users u
JOIN orders o ON u.user_id = o.user_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE o.order_status = 'delivered'
AND o.created_at >= '2024-01-01'
ORDER BY o.created_at DESC
LIMIT 10;
Show detailed execution information
SHOW WARNINGS;
Create covering indexes for complex queries
Implement covering indexes that include all columns needed for queries to avoid table lookups.
# Create covering index for order analysis queries
CREATE INDEX idx_orders_covering ON orders (order_status, created_at, user_id, order_id, total_amount);
Create covering index for product searches
CREATE INDEX idx_products_covering ON products (category_id, price, name, product_id, stock_quantity);
Create covering index for user order analysis
CREATE INDEX idx_users_covering ON users (status, created_at, user_id, username, email);
Analyze index usage
ANALYZE TABLE users, products, orders, order_items;
Configure Performance Schema for query profiling
Set up Performance Schema consumers and instruments for detailed query analysis.
# Enable statement profiling instruments
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%statement%';
Enable stage profiling for query execution phases
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%stage%';
Enable wait event profiling
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%wait/io%';
Configure statement history retention
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME IN (
'events_statements_current',
'events_statements_history',
'events_statements_history_long'
);
Create query performance monitoring views
Build custom views to easily identify slow queries and performance bottlenecks.
# Create view for top slow queries
CREATE VIEW slow_queries_summary AS
SELECT
DIGEST_TEXT as query_pattern,
COUNT_STAR as exec_count,
AVG_TIMER_WAIT/1000000000000 as avg_time_sec,
MAX_TIMER_WAIT/1000000000000 as max_time_sec,
SUM_TIMER_WAIT/1000000000000 as total_time_sec,
SUM_ROWS_EXAMINED as total_rows_examined,
SUM_ROWS_SENT as total_rows_sent
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT IS NOT NULL
ORDER BY AVG_TIMER_WAIT DESC;
Create view for index usage analysis
CREATE VIEW index_usage_stats AS
SELECT
OBJECT_SCHEMA as db_name,
OBJECT_NAME as table_name,
INDEX_NAME as index_name,
COUNT_FETCH as index_fetches,
COUNT_INSERT as index_inserts,
COUNT_UPDATE as index_updates,
COUNT_DELETE as index_deletes
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA = 'ecommerce_db'
ORDER BY COUNT_FETCH DESC;
Set up automated slow query analysis script
Create a monitoring script that parses slow query logs and generates performance reports.
#!/bin/bash
MariaDB Performance Monitoring Script
Analyzes slow queries and generates performance reports
LOG_FILE="/var/log/mysql/mysql-slow.log"
REPORT_FILE="/var/log/mysql/performance_report_$(date +%Y%m%d_%H%M%S).txt"
ALERT_THRESHOLD=5.0 # Alert for queries taking more than 5 seconds
echo "MariaDB Performance Report - $(date)" > "$REPORT_FILE"
echo "=============================================" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
Check if slow query log exists
if [[ ! -f "$LOG_FILE" ]]; then
echo "Error: Slow query log not found at $LOG_FILE" >> "$REPORT_FILE"
exit 1
fi
Analyze slow queries using mysqldumpslow
echo "Top 10 Slowest Query Patterns:" >> "$REPORT_FILE"
echo "------------------------------" >> "$REPORT_FILE"
mysqldumpslow -s t -t 10 "$LOG_FILE" >> "$REPORT_FILE" 2>/dev/null
echo "" >> "$REPORT_FILE"
echo "Top 10 Most Frequent Slow Queries:" >> "$REPORT_FILE"
echo "----------------------------------" >> "$REPORT_FILE"
mysqldumpslow -s c -t 10 "$LOG_FILE" >> "$REPORT_FILE" 2>/dev/null
echo "" >> "$REPORT_FILE"
Query Performance Schema for current statistics
echo "Current Performance Metrics:" >> "$REPORT_FILE"
echo "---------------------------" >> "$REPORT_FILE"
mysql -u root -e "
SELECT
'Total Queries' as metric,
FORMAT(SUM(COUNT_STAR), 0) as value
FROM performance_schema.events_statements_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'statement/sql/%'
UNION ALL
SELECT
'Avg Query Time (ms)' as metric,
FORMAT(AVG(AVG_TIMER_WAIT)/1000000000, 2) as value
FROM performance_schema.events_statements_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'statement/sql/%' AND COUNT_STAR > 0
UNION ALL
SELECT
'Queries > ${ALERT_THRESHOLD}s' as metric,
COUNT(*) as value
FROM performance_schema.events_statements_history_long
WHERE TIMER_WAIT > ${ALERT_THRESHOLD}000000000000;
" >> "$REPORT_FILE" 2>/dev/null
echo "" >> "$REPORT_FILE"
echo "Index Usage Analysis:" >> "$REPORT_FILE"
echo "--------------------" >> "$REPORT_FILE"
mysql -u root -e "
SELECT
CONCAT(OBJECT_SCHEMA, '.', OBJECT_NAME) as table_name,
INDEX_NAME,
FORMAT(COUNT_FETCH, 0) as fetches,
FORMAT(COUNT_INSERT, 0) as inserts,
FORMAT(COUNT_UPDATE, 0) as updates,
FORMAT(COUNT_DELETE, 0) as deletes
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND COUNT_FETCH > 0
ORDER BY COUNT_FETCH DESC
LIMIT 20;
" >> "$REPORT_FILE" 2>/dev/null
echo "Performance report generated: $REPORT_FILE"
Check for critical performance issues
SLOW_QUERIES=$(mysql -u root -s -e "SELECT COUNT(*) FROM performance_schema.events_statements_history_long WHERE TIMER_WAIT > ${ALERT_THRESHOLD}000000000000;" 2>/dev/null)
if [[ "$SLOW_QUERIES" -gt 10 ]]; then
echo "WARNING: $SLOW_QUERIES queries detected taking longer than ${ALERT_THRESHOLD} seconds"
# Send alert email (configure mail system separately)
# echo "Critical performance alert: $SLOW_QUERIES slow queries detected" | mail -s "MariaDB Performance Alert" admin@example.com
fi
Make monitoring script executable and schedule it
Set up automated performance monitoring with proper permissions and cron scheduling.
sudo chown root:root /usr/local/bin/mariadb_performance_monitor.sh
sudo chmod 755 /usr/local/bin/mariadb_performance_monitor.sh
# Create log directory for reports
sudo mkdir -p /var/log/mysql/reports
sudo chown mysql:mysql /var/log/mysql/reports
sudo chmod 775 /var/log/mysql/reports
# Schedule monitoring script to run every hour
sudo crontab -e
# MariaDB Performance Monitoring - runs every hour
0 /usr/local/bin/mariadb_performance_monitor.sh >/dev/null 2>&1
Weekly slow query log rotation
0 0 0 /usr/sbin/logrotate -f /etc/logrotate.d/mysql-server
Configure query optimization settings
Fine-tune MariaDB optimizer settings for better query execution plans and performance.
[mysqld]
Query optimizer settings
optimizer_search_depth = 62
optimizer_prune_level = 1
optimizer_use_condition_selectivity = 4
Join buffer optimization
join_buffer_size = 2M
join_buffer_space_limit = 16M
Sort and temporary table optimization
sort_buffer_size = 2M
tmp_table_size = 64M
max_heap_table_size = 64M
Thread and connection optimization
thread_cache_size = 16
table_open_cache = 4096
table_definition_cache = 2048
InnoDB optimization for high concurrency
innodb_thread_concurrency = 0
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_flush_method = O_DIRECT
innodb_adaptive_hash_index = ON
innodb_stats_on_metadata = OFF
Apply optimization settings and restart
Restart MariaDB to apply the new optimization configuration.
sudo systemctl restart mariadb
sudo systemctl status mariadb
Test query performance improvements
Execute test queries and compare performance before and after optimization.
sudo mysql -u root -p ecommerce_db
# Test complex query performance
SET profiling = 1;
SELECT
u.username,
COUNT(o.order_id) as total_orders,
SUM(o.total_amount) as total_spent,
AVG(o.total_amount) as avg_order_value
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE u.status = 'active'
GROUP BY u.user_id, u.username
HAVING total_orders > 0
ORDER BY total_spent DESC;
Show query profiling information
SHOW PROFILES;
SHOW PROFILE FOR QUERY 1;
Check index usage for the query
EXPLAIN EXTENDED
SELECT
u.username,
COUNT(o.order_id) as total_orders,
SUM(o.total_amount) as total_spent,
AVG(o.total_amount) as avg_order_value
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE u.status = 'active'
GROUP BY u.user_id, u.username
HAVING total_orders > 0
ORDER BY total_spent DESC;
Verify your setup
# Check Performance Schema status
sudo mysql -u root -e "SHOW VARIABLES LIKE 'performance_schema';"
Verify slow query log is enabled
sudo mysql -u root -e "SHOW VARIABLES LIKE 'slow_query_log%';"
Check current slow queries
sudo mysql -u root -e "SELECT COUNT(*) as slow_queries FROM performance_schema.events_statements_history_long WHERE TIMER_WAIT > 2000000000000;"
Verify monitoring script
sudo /usr/local/bin/mariadb_performance_monitor.sh
Check index usage
sudo mysql -u root -e "SELECT TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX, COLUMN_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'ecommerce_db' ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;"
Test query cache hit rate
sudo mysql -u root -e "SHOW STATUS LIKE 'Qcache%';"
Check buffer pool usage
sudo mysql -u root -e "SHOW STATUS LIKE 'Innodb_buffer_pool%';"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Performance Schema not working | Not enabled in configuration | Add performance_schema = ON to config and restart |
| Slow query log empty | long_query_time set too high | Lower long_query_time = 1 to capture more queries |
| High CPU usage after optimization | InnoDB settings too aggressive | Reduce innodb_io_capacity and innodb_thread_concurrency |
| Monitoring script fails | Permission issues or missing mysqldumpslow | Check file permissions with ls -la and install mysql-client tools |
| Queries still slow after indexing | Wrong index order or missing covering index | Use EXPLAIN to verify index usage and create covering indexes |
| Memory usage too high | Buffer pool or cache sizes too large | Reduce innodb_buffer_pool_size to 70% of available RAM |
Next steps
- Configure MariaDB 11.6 master-slave replication with SSL encryption and automatic failover
- Set up Prometheus and Grafana monitoring stack with Docker compose
- Implement MariaDB connection pooling with ProxySQL for high availability
- Configure MariaDB ColumnStore for high-performance analytics workloads
- Set up MariaDB Galera Cluster for multi-master replication and automatic failover
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'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Global variables
MYSQL_ROOT_PASSWORD=""
BACKUP_DIR="/tmp/mariadb_backup_$(date +%Y%m%d_%H%M%S)"
# Cleanup function for rollback
cleanup() {
echo -e "${RED}Error occurred. Cleaning up...${NC}"
if [[ -d "$BACKUP_DIR" ]]; then
echo "Restoring original configuration..."
if [[ -f "$BACKUP_DIR/50-server.cnf" ]]; then
cp "$BACKUP_DIR/50-server.cnf" "$MARIADB_CONFIG_FILE" 2>/dev/null || true
fi
fi
}
trap cleanup ERR
usage() {
echo "Usage: $0 [mysql_root_password]"
echo " mysql_root_password: MariaDB root password (optional, will prompt if not provided)"
exit 1
}
log() {
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
success() {
echo -e "${GREEN}✓${NC} $1"
}
warning() {
echo -e "${YELLOW}⚠${NC} $1"
}
error() {
echo -e "${RED}✗${NC} $1"
}
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root or with sudo"
exit 1
fi
# Parse arguments
if [[ $# -gt 1 ]]; then
usage
fi
if [[ $# -eq 1 ]]; then
MYSQL_ROOT_PASSWORD="$1"
fi
# Auto-detect distribution
if [[ -f /etc/os-release ]]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
MARIADB_SERVICE="mariadb"
MARIADB_CONFIG_FILE="/etc/mysql/mariadb.conf.d/50-server.cnf"
MYSQL_LOG_DIR="/var/log/mysql"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
MARIADB_SERVICE="mariadb"
MARIADB_CONFIG_FILE="/etc/my.cnf.d/server.cnf"
MYSQL_LOG_DIR="/var/log/mariadb"
;;
fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
MARIADB_SERVICE="mariadb"
MARIADB_CONFIG_FILE="/etc/my.cnf.d/mariadb-server.cnf"
MYSQL_LOG_DIR="/var/log/mariadb"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
MARIADB_SERVICE="mariadb"
MARIADB_CONFIG_FILE="/etc/my.cnf.d/server.cnf"
MYSQL_LOG_DIR="/var/log/mariadb"
;;
*)
error "Unsupported distribution: $ID"
exit 1
;;
esac
else
error "Cannot detect distribution"
exit 1
fi
log "Starting MariaDB 11.6 Performance Optimization Setup for $PRETTY_NAME"
# Step 1: Update system and install MariaDB
echo -e "${BLUE}[1/8]${NC} Updating system and installing MariaDB..."
$PKG_UPDATE
# Install MariaDB based on distribution
case "$ID" in
ubuntu|debian)
$PKG_INSTALL software-properties-common dirmngr apt-transport-https
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | bash -s -- --mariadb-server-version=11.6
$PKG_UPDATE
$PKG_INSTALL mariadb-server mariadb-client
;;
*)
$PKG_INSTALL mariadb-server mariadb
;;
esac
success "MariaDB installed successfully"
# Step 2: Create backup directory and backup original config
echo -e "${BLUE}[2/8]${NC} Creating backup of original configuration..."
mkdir -p "$BACKUP_DIR"
if [[ -f "$MARIADB_CONFIG_FILE" ]]; then
cp "$MARIADB_CONFIG_FILE" "$BACKUP_DIR/"
fi
success "Configuration backed up to $BACKUP_DIR"
# Step 3: Start and enable MariaDB service
echo -e "${BLUE}[3/8]${NC} Starting and enabling MariaDB service..."
systemctl enable $MARIADB_SERVICE
systemctl start $MARIADB_SERVICE
if ! systemctl is-active --quiet $MARIADB_SERVICE; then
error "Failed to start MariaDB service"
exit 1
fi
success "MariaDB service started and enabled"
# Step 4: Secure MariaDB installation
echo -e "${BLUE}[4/8]${NC} Securing MariaDB installation..."
if [[ -z "$MYSQL_ROOT_PASSWORD" ]]; then
read -s -p "Enter MariaDB root password: " MYSQL_ROOT_PASSWORD
echo
fi
# Create log directory
mkdir -p "$MYSQL_LOG_DIR"
chown mysql:mysql "$MYSQL_LOG_DIR"
chmod 755 "$MYSQL_LOG_DIR"
# Set root password and secure installation
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';" 2>/dev/null || \
mysql -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('$MYSQL_ROOT_PASSWORD');"
success "MariaDB installation secured"
# Step 5: Configure MariaDB for high performance
echo -e "${BLUE}[5/8]${NC} Configuring MariaDB for high performance..."
# Ensure config directory exists
mkdir -p "$(dirname "$MARIADB_CONFIG_FILE")"
# Create optimized configuration
cat > "$MARIADB_CONFIG_FILE" << 'EOF'
[mysqld]
# Performance Schema configuration
performance_schema = ON
performance_schema_consumer_events_statements_current = ON
performance_schema_consumer_events_statements_history = ON
performance_schema_consumer_events_statements_history_long = ON
# Slow query log configuration
slow_query_log = 1
long_query_time = 2
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_slow_slave_statements = 1
# Query cache optimization
query_cache_type = 1
query_cache_size = 268435456
query_cache_limit = 2097152
# Connection and buffer optimizations
max_connections = 500
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 512M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
# Additional performance tuning
innodb_thread_concurrency = 0
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_io_capacity = 1000
innodb_flush_method = O_DIRECT
tmp_table_size = 256M
max_heap_table_size = 256M
key_buffer_size = 512M
sort_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 128M
thread_cache_size = 100
table_open_cache = 4000
EOF
# Set log file path based on distribution
echo "slow_query_log_file = $MYSQL_LOG_DIR/mysql-slow.log" >> "$MARIADB_CONFIG_FILE"
chmod 644 "$MARIADB_CONFIG_FILE"
chown root:root "$MARIADB_CONFIG_FILE"
success "MariaDB configuration updated"
# Step 6: Restart MariaDB to apply configuration
echo -e "${BLUE}[6/8]${NC} Restarting MariaDB to apply configuration..."
systemctl restart $MARIADB_SERVICE
if ! systemctl is-active --quiet $MARIADB_SERVICE; then
error "Failed to restart MariaDB with new configuration"
exit 1
fi
success "MariaDB restarted successfully"
# Step 7: Create sample database and schema
echo -e "${BLUE}[7/8]${NC} Creating sample e-commerce database schema..."
mysql -u root -p"$MYSQL_ROOT_PASSWORD" << 'EOF'
CREATE DATABASE IF NOT EXISTS ecommerce_db;
USE ecommerce_db;
CREATE TABLE IF NOT EXISTS users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL,
status ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
INDEX idx_email (email),
INDEX idx_status_created (status, created_at)
);
CREATE TABLE IF NOT EXISTS products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
category_id INT NOT NULL,
price DECIMAL(10,2) NOT NULL,
stock_quantity INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category_price (category_id, price),
INDEX idx_stock (stock_quantity),
INDEX idx_name (name)
);
CREATE TABLE IF NOT EXISTS orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
total_amount DECIMAL(10,2) NOT NULL,
order_status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id),
INDEX idx_user_status (user_id, order_status),
INDEX idx_status_date (order_status, created_at),
INDEX idx_created_at (created_at)
);
CREATE TABLE IF NOT EXISTS order_items (
item_id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id),
INDEX idx_order_product (order_id, product_id),
INDEX idx_product_id (product_id)
);
EOF
success "Sample database schema created"
# Step 8: Verification and final setup
echo -e "${BLUE}[8/8]${NC} Verifying installation and configuration..."
# Check MariaDB version and status
MARIADB_VERSION=$(mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SELECT VERSION();" --batch --skip-column-names 2>/dev/null)
if [[ -n "$MARIADB_VERSION" ]]; then
success "MariaDB $MARIADB_VERSION is running"
else
error "Failed to verify MariaDB installation"
exit 1
fi
# Verify performance schema is enabled
PERF_SCHEMA=$(mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW VARIABLES LIKE 'performance_schema';" --batch --skip-column-names 2>/dev/null | awk '{print $2}')
if [[ "$PERF_SCHEMA" == "ON" ]]; then
success "Performance Schema is enabled"
else
warning "Performance Schema is not enabled"
fi
# Verify slow query log is enabled
SLOW_LOG=$(mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW VARIABLES LIKE 'slow_query_log';" --batch --skip-column-names 2>/dev/null | awk '{print $2}')
if [[ "$SLOW_LOG" == "ON" ]]; then
success "Slow query log is enabled"
else
warning "Slow query log is not enabled"
fi
# Create monitoring script
cat > /usr/local/bin/mariadb-monitor << 'MONITOR_EOF'
#!/bin/bash
echo "=== MariaDB Performance Monitor ==="
echo "Slow query log: $(mysql -u root -p"$1" -e "SHOW VARIABLES LIKE 'slow_query_log';" --batch --skip-column-names 2>/dev/null | awk '{print $2}')"
echo "Query cache hit rate:"
mysql -u root -p"$1" -e "SHOW STATUS LIKE 'Qcache%';" 2>/dev/null
echo -e "\nRecent slow queries:"
tail -20 /var/log/*/mysql-slow.log 2>/dev/null || echo "No slow queries logged yet"
MONITOR_EOF
chmod 755 /usr/local/bin/mariadb-monitor
success "Monitoring script created at /usr/local/bin/mariadb-monitor"
echo
log "MariaDB 11.6 Performance Optimization Setup Complete!"
echo
echo -e "${GREEN}Next Steps:${NC}"
echo "1. Monitor slow queries: tail -f $MYSQL_LOG_DIR/mysql-slow.log"
echo "2. Run performance monitor: /usr/local/bin/mariadb-monitor [root_password]"
echo "3. Connect to database: mysql -u root -p"
echo "4. Use ecommerce_db for testing: USE ecommerce_db;"
echo
echo -e "${YELLOW}Important:${NC}"
echo "- Configuration backup saved to: $BACKUP_DIR"
echo "- Log files location: $MYSQL_LOG_DIR"
echo "- Consider tuning buffer sizes based on your available RAM"
echo
success "Setup completed successfully!"
Review the script before running. Execute with: bash install.sh