MySQL/MariaDB Database Setup Guide
Table of Contents
1. [Introduction](#introduction) 2. [Installation](#installation) 3. [Initial Configuration](#initial-configuration) 4. [Database Operations](#database-operations) 5. [User Management](#user-management) 6. [Security Configuration](#security-configuration) 7. [Performance Optimization](#performance-optimization) 8. [Backup and Recovery](#backup-and-recovery) 9. [Monitoring and Maintenance](#monitoring-and-maintenance) 10. [Troubleshooting](#troubleshooting)Introduction
MySQL and MariaDB are popular open-source relational database management systems (RDBMS) that serve as the backbone for many web applications and enterprise solutions. MySQL was originally developed by Oracle Corporation, while MariaDB is a community-driven fork created by the original MySQL developers to ensure continued open-source development.
Key Differences Between MySQL and MariaDB
| Feature | MySQL | MariaDB | |---------|--------|---------| | License | GPL with commercial options | GPL | | Storage Engines | InnoDB, MyISAM, Memory | All MySQL engines plus Aria, TokuDB, Spider | | JSON Support | Native JSON data type | JSON functions with TEXT storage | | Performance | Optimized for general use | Enhanced performance features | | Compatibility | Standard MySQL | Fully compatible with MySQL | | Development | Oracle-driven | Community-driven |
System Requirements
| Component | Minimum | Recommended | |-----------|---------|-------------| | RAM | 512 MB | 4 GB or more | | Disk Space | 200 MB | 2 GB or more | | CPU | 1 Core | 2+ Cores | | Operating System | Linux, Windows, macOS | Linux preferred |
Installation
Ubuntu/Debian Installation
#### MySQL Installation
`bash
Update package index
sudo apt updateInstall MySQL server
sudo apt install mysql-serverCheck MySQL service status
sudo systemctl status mysqlEnable MySQL to start on boot
sudo systemctl enable mysql`#### MariaDB Installation
`bash
Update package index
sudo apt updateInstall MariaDB server
sudo apt install mariadb-serverCheck MariaDB service status
sudo systemctl status mariadbEnable MariaDB to start on boot
sudo systemctl enable mariadb`CentOS/RHEL/Rocky Linux Installation
#### MySQL Installation
`bash
Install MySQL repository
sudo dnf install mysql-serverStart MySQL service
sudo systemctl start mysqldEnable MySQL to start on boot
sudo systemctl enable mysqldCheck service status
sudo systemctl status mysqld`#### MariaDB Installation
`bash
Install MariaDB server
sudo dnf install mariadb-serverStart MariaDB service
sudo systemctl start mariadbEnable MariaDB to start on boot
sudo systemctl enable mariadbCheck service status
sudo systemctl status mariadb`Windows Installation
#### MySQL on Windows 1. Download MySQL Installer from official MySQL website 2. Run the installer as administrator 3. Choose setup type (Developer Default, Server Only, etc.) 4. Configure MySQL Server with desired settings 5. Set root password during installation 6. Complete installation and start MySQL service
#### MariaDB on Windows 1. Download MariaDB MSI installer from official website 2. Run installer as administrator 3. Follow installation wizard 4. Set root password 5. Configure service startup options 6. Complete installation
Docker Installation
#### MySQL Docker Container
`bash
Pull MySQL image
docker pull mysql:8.0Run MySQL container
docker run --name mysql-server \ -e MYSQL_ROOT_PASSWORD=your_password \ -p 3306:3306 \ -d mysql:8.0Connect to MySQL container
docker exec -it mysql-server mysql -u root -p`#### MariaDB Docker Container
`bash
Pull MariaDB image
docker pull mariadb:10.6Run MariaDB container
docker run --name mariadb-server \ -e MYSQL_ROOT_PASSWORD=your_password \ -p 3306:3306 \ -d mariadb:10.6Connect to MariaDB container
docker exec -it mariadb-server mysql -u root -p`Initial Configuration
Secure Installation
Both MySQL and MariaDB provide security scripts to improve initial security:
#### MySQL Secure Installation
`bash
Run MySQL secure installation script
sudo mysql_secure_installation`#### MariaDB Secure Installation
`bash
Run MariaDB secure installation script
sudo mysql_secure_installation`The secure installation script will prompt for the following configurations:
| Configuration Option | Recommendation | Purpose | |---------------------|----------------|---------| | Set root password | Yes | Secure root account | | Remove anonymous users | Yes | Eliminate security risk | | Disallow root login remotely | Yes | Prevent remote root access | | Remove test database | Yes | Remove unnecessary test data | | Reload privilege tables | Yes | Apply security changes |
Configuration Files
#### MySQL Configuration File Locations
| Operating System | Configuration File Path | |------------------|------------------------| | Linux | /etc/mysql/mysql.conf.d/mysqld.cnf | | CentOS/RHEL | /etc/my.cnf | | Windows | C:\ProgramData\MySQL\MySQL Server 8.0\my.ini |
#### MariaDB Configuration File Locations
| Operating System | Configuration File Path | |------------------|------------------------| | Linux | /etc/mysql/mariadb.conf.d/50-server.cnf | | CentOS/RHEL | /etc/my.cnf.d/server.cnf | | Windows | C:\Program Files\MariaDB\data\my.ini |
Basic Configuration Parameters
`ini
[mysqld]
Basic Settings
port = 3306 bind-address = 127.0.0.1 datadir = /var/lib/mysql socket = /var/run/mysqld/mysqld.sockCharacter Set and Collation
character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ciConnection Settings
max_connections = 100 connect_timeout = 10 wait_timeout = 28800Buffer Settings
innodb_buffer_pool_size = 1G key_buffer_size = 256M query_cache_size = 64MLog Settings
log-error = /var/log/mysql/error.log slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2Binary Logging
log-bin = mysql-bin binlog_format = ROW expire_logs_days = 7`Database Operations
Connecting to Database
#### Command Line Connection
`bash
Connect as root user
mysql -u root -pConnect to specific database
mysql -u username -p database_nameConnect to remote server
mysql -h hostname -u username -p database_nameConnect with specific port
mysql -h hostname -P 3306 -u username -p`#### Connection Parameters
| Parameter | Description | Example | |-----------|-------------|---------| | -u | Username | -u root | | -p | Password (prompt) | -p | | -h | Hostname | -h localhost | | -P | Port number | -P 3306 | | -D | Database name | -D mydb | | -e | Execute command | -e "SHOW DATABASES;" |
Database Management Commands
#### Creating Databases
`sql
-- Create a new database
CREATE DATABASE company_db;
-- Create database with character set CREATE DATABASE company_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Create database if it doesn't exist
CREATE DATABASE IF NOT EXISTS company_db;
`
#### Database Information Commands
`sql
-- Show all databases
SHOW DATABASES;
-- Select a database to use USE company_db;
-- Show current database SELECT DATABASE();
-- Show database creation statement
SHOW CREATE DATABASE company_db;
`
#### Dropping Databases
`sql
-- Drop a database
DROP DATABASE company_db;
-- Drop database if it exists
DROP DATABASE IF EXISTS company_db;
`
Table Operations
#### Creating Tables
`sql
-- Create a basic table
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
hire_date DATE,
salary DECIMAL(10,2),
department_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create table with foreign key CREATE TABLE departments ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, manager_id INT, budget DECIMAL(15,2) );
-- Add foreign key constraint
ALTER TABLE employees
ADD CONSTRAINT fk_department
FOREIGN KEY (department_id) REFERENCES departments(id);
`
#### Table Information Commands
`sql
-- Show all tables
SHOW TABLES;
-- Describe table structure DESCRIBE employees; -- or DESC employees;
-- Show table creation statement SHOW CREATE TABLE employees;
-- Show table status
SHOW TABLE STATUS LIKE 'employees';
`
#### Modifying Tables
`sql
-- Add a new column
ALTER TABLE employees
ADD COLUMN phone VARCHAR(20);
-- Modify existing column ALTER TABLE employees MODIFY COLUMN phone VARCHAR(25);
-- Rename a column ALTER TABLE employees CHANGE COLUMN phone phone_number VARCHAR(25);
-- Drop a column ALTER TABLE employees DROP COLUMN phone_number;
-- Add index CREATE INDEX idx_last_name ON employees(last_name);
-- Add unique constraint
ALTER TABLE employees
ADD CONSTRAINT uk_email UNIQUE (email);
`
Data Manipulation
#### Inserting Data
`sql
-- Insert single record
INSERT INTO departments (name, budget)
VALUES ('Engineering', 500000.00);
-- Insert multiple records INSERT INTO employees (first_name, last_name, email, hire_date, salary, department_id) VALUES ('John', 'Doe', 'john.doe@company.com', '2023-01-15', 75000.00, 1), ('Jane', 'Smith', 'jane.smith@company.com', '2023-02-01', 80000.00, 1), ('Mike', 'Johnson', 'mike.johnson@company.com', '2023-03-10', 70000.00, 1);
-- Insert with SELECT
INSERT INTO employees (first_name, last_name, email, salary, department_id)
SELECT first_name, last_name, email, salary, department_id
FROM temp_employees
WHERE active = 1;
`
#### Querying Data
`sql
-- Basic SELECT
SELECT * FROM employees;
-- SELECT specific columns SELECT first_name, last_name, salary FROM employees;
-- SELECT with WHERE clause SELECT * FROM employees WHERE salary > 75000;
-- SELECT with JOIN SELECT e.first_name, e.last_name, d.name as department_name FROM employees e JOIN departments d ON e.department_id = d.id;
-- SELECT with aggregation SELECT department_id, COUNT(*) as employee_count, AVG(salary) as avg_salary FROM employees GROUP BY department_id;
-- SELECT with ordering SELECT * FROM employees ORDER BY salary DESC, last_name ASC;
-- SELECT with LIMIT
SELECT * FROM employees
ORDER BY hire_date DESC
LIMIT 10;
`
#### Updating Data
`sql
-- Update single record
UPDATE employees
SET salary = 85000.00
WHERE id = 1;
-- Update multiple records UPDATE employees SET salary = salary * 1.05 WHERE department_id = 1;
-- Update with JOIN
UPDATE employees e
JOIN departments d ON e.department_id = d.id
SET e.salary = e.salary * 1.10
WHERE d.name = 'Engineering';
`
#### Deleting Data
`sql
-- Delete specific records
DELETE FROM employees
WHERE id = 1;
-- Delete with condition DELETE FROM employees WHERE hire_date < '2022-01-01';
-- Delete with JOIN
DELETE e FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE d.name = 'Discontinued';
`
User Management
Creating Users
`sql
-- Create user with password
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'secure_password';
-- Create user for remote access CREATE USER 'remote_user'@'%' IDENTIFIED BY 'secure_password';
-- Create user for specific IP
CREATE USER 'api_user'@'192.168.1.100' IDENTIFIED BY 'secure_password';
`
User Information Commands
`sql
-- Show all users
SELECT User, Host FROM mysql.user;
-- Show current user SELECT USER(), CURRENT_USER();
-- Show user privileges SHOW GRANTS FOR 'app_user'@'localhost';
-- Show all grants for current user
SHOW GRANTS;
`
Granting Privileges
#### Database-Level Privileges
`sql
-- Grant all privileges on specific database
GRANT ALL PRIVILEGES ON company_db.* TO 'app_user'@'localhost';
-- Grant specific privileges GRANT SELECT, INSERT, UPDATE, DELETE ON company_db.* TO 'app_user'@'localhost';
-- Grant read-only access
GRANT SELECT ON company_db.* TO 'readonly_user'@'localhost';
`
#### Table-Level Privileges
`sql
-- Grant privileges on specific table
GRANT SELECT, INSERT, UPDATE ON company_db.employees TO 'hr_user'@'localhost';
-- Grant column-specific privileges
GRANT SELECT (first_name, last_name, email) ON company_db.employees TO 'limited_user'@'localhost';
`
#### Global Privileges
`sql
-- Grant global privileges (use carefully)
GRANT CREATE, DROP ON . TO 'admin_user'@'localhost';
-- Grant replication privileges
GRANT REPLICATION SLAVE ON . TO 'repl_user'@'%';
`
Privilege Types
| Privilege | Description | Level | |-----------|-------------|-------| | ALL PRIVILEGES | All available privileges | Global, Database, Table | | SELECT | Read data | Global, Database, Table, Column | | INSERT | Insert new records | Global, Database, Table, Column | | UPDATE | Modify existing records | Global, Database, Table, Column | | DELETE | Remove records | Global, Database, Table | | CREATE | Create databases and tables | Global, Database | | DROP | Drop databases and tables | Global, Database | | ALTER | Modify table structure | Global, Database, Table | | INDEX | Create and drop indexes | Global, Database, Table | | GRANT OPTION | Grant privileges to other users | Global, Database, Table |
Revoking Privileges
`sql
-- Revoke specific privileges
REVOKE INSERT, UPDATE ON company_db.* FROM 'app_user'@'localhost';
-- Revoke all privileges REVOKE ALL PRIVILEGES ON company_db.* FROM 'app_user'@'localhost';
-- Revoke grant option
REVOKE GRANT OPTION ON company_db.* FROM 'app_user'@'localhost';
`
User Management
`sql
-- Change user password
ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'new_password';
-- Rename user RENAME USER 'old_user'@'localhost' TO 'new_user'@'localhost';
-- Drop user DROP USER 'app_user'@'localhost';
-- Lock user account ALTER USER 'app_user'@'localhost' ACCOUNT LOCK;
-- Unlock user account ALTER USER 'app_user'@'localhost' ACCOUNT UNLOCK;
-- Apply privilege changes
FLUSH PRIVILEGES;
`
Security Configuration
Password Policies
#### MySQL 8.0 Password Validation
`sql
-- Install password validation plugin
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- Check password validation settings SHOW VARIABLES LIKE 'validate_password%';
-- Set password policy
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;
`
SSL/TLS Configuration
#### Enabling SSL
`ini
[mysqld]
SSL Configuration
ssl-ca=/etc/mysql/ssl/ca-cert.pem ssl-cert=/etc/mysql/ssl/server-cert.pem ssl-key=/etc/mysql/ssl/server-key.pem require_secure_transport=ON`#### Creating SSL Certificates
`bash
Generate CA private key
openssl genrsa 2048 > ca-key.pemGenerate CA certificate
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca-cert.pemGenerate server private key
openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pemGenerate server certificate
openssl rsa -in server-key.pem -out server-key.pem openssl x509 -req -in server-req.pem -days 3600 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem`Firewall Configuration
#### UFW (Ubuntu/Debian)
`bash
Allow MySQL port
sudo ufw allow 3306/tcpAllow from specific IP
sudo ufw allow from 192.168.1.100 to any port 3306Allow from subnet
sudo ufw allow from 192.168.1.0/24 to any port 3306`#### Firewalld (CentOS/RHEL)
`bash
Allow MySQL service
sudo firewall-cmd --permanent --add-service=mysql sudo firewall-cmd --reloadAllow from specific IP
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' port protocol='tcp' port='3306' accept" sudo firewall-cmd --reload`Audit Logging
#### Enable Audit Plugin
`sql
-- Install audit log plugin
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- Configure audit logging
SET GLOBAL audit_log_policy = ALL;
SET GLOBAL audit_log_format = JSON;
SET GLOBAL audit_log_file = '/var/log/mysql/audit.log';
`
Performance Optimization
Key Configuration Parameters
#### Memory Settings
`ini
[mysqld]
InnoDB Buffer Pool (70-80% of available RAM)
innodb_buffer_pool_size = 4G innodb_buffer_pool_instances = 4Query Cache (MySQL 5.7 and earlier)
query_cache_type = 1 query_cache_size = 256MKey Buffer (for MyISAM tables)
key_buffer_size = 256MSort and Join Buffers
sort_buffer_size = 2M join_buffer_size = 2M read_buffer_size = 1M read_rnd_buffer_size = 1M`#### Connection Settings
`ini
[mysqld]
Connection Limits
max_connections = 200 max_connect_errors = 1000000 connect_timeout = 10 wait_timeout = 28800 interactive_timeout = 28800Thread Settings
thread_cache_size = 50 thread_stack = 256K`#### InnoDB Settings
`ini
[mysqld]
InnoDB Log Settings
innodb_log_file_size = 1G innodb_log_buffer_size = 16M innodb_flush_log_at_trx_commit = 2InnoDB I/O Settings
innodb_io_capacity = 1000 innodb_io_capacity_max = 2000 innodb_read_io_threads = 8 innodb_write_io_threads = 8InnoDB Lock Settings
innodb_lock_wait_timeout = 50`Index Optimization
#### Creating Effective Indexes
`sql
-- Single column index
CREATE INDEX idx_last_name ON employees(last_name);
-- Composite index CREATE INDEX idx_dept_salary ON employees(department_id, salary);
-- Unique index CREATE UNIQUE INDEX idx_email ON employees(email);
-- Partial index (MySQL 8.0+) CREATE INDEX idx_active_employees ON employees(department_id) WHERE status = 'active';
-- Functional index (MySQL 8.0+)
CREATE INDEX idx_email_domain ON employees((SUBSTRING_INDEX(email, '@', -1)));
`
#### Index Analysis
`sql
-- Show indexes for a table
SHOW INDEX FROM employees;
-- Analyze index usage EXPLAIN SELECT * FROM employees WHERE last_name = 'Smith';
-- Show index statistics
SELECT
table_name,
index_name,
column_name,
cardinality
FROM information_schema.statistics
WHERE table_schema = 'company_db';
`
Query Optimization
#### Using EXPLAIN
`sql
-- Basic EXPLAIN
EXPLAIN SELECT * FROM employees WHERE salary > 75000;
-- Extended EXPLAIN EXPLAIN FORMAT=JSON SELECT e.first_name, e.last_name, d.name FROM employees e JOIN departments d ON e.department_id = d.id WHERE e.salary > 75000;
-- EXPLAIN ANALYZE (MySQL 8.0+)
EXPLAIN ANALYZE SELECT * FROM employees WHERE salary > 75000;
`
#### Query Optimization Techniques
| Technique | Description | Example | |-----------|-------------|---------| | Use Indexes | Create appropriate indexes | CREATE INDEX idx_salary ON employees(salary) | | Limit Results | Use LIMIT clause | SELECT * FROM employees LIMIT 100 | | Select Specific Columns | Avoid SELECT * | SELECT id, name FROM employees | | Use EXISTS | Instead of IN with subqueries | WHERE EXISTS (SELECT 1 FROM...) | | Optimize JOINs | Use proper JOIN conditions | ON e.id = d.employee_id | | Use UNION ALL | Instead of UNION when duplicates allowed | SELECT ... UNION ALL SELECT ... |
Monitoring Performance
#### Key Performance Metrics
`sql
-- Show global status
SHOW GLOBAL STATUS;
-- Show process list SHOW PROCESSLIST;
-- Show engine status SHOW ENGINE INNODB STATUS;
-- Query performance metrics
SELECT
schema_name,
digest_text,
count_star,
avg_timer_wait/1000000000000 as avg_time_sec,
sum_rows_examined,
sum_rows_sent
FROM performance_schema.events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC
LIMIT 10;
`
#### Performance Schema Configuration
`ini
[mysqld]
Enable Performance Schema
performance_schema = ON performance-schema-instrument = 'statement/%=ON' performance-schema-consumer-events-statements-current = ON performance-schema-consumer-events-statements-history = ON performance-schema-consumer-events-statements-history-long = ON`Backup and Recovery
Logical Backups
#### Using mysqldump
`bash
Backup single database
mysqldump -u root -p company_db > company_db_backup.sqlBackup multiple databases
mysqldump -u root -p --databases db1 db2 > multiple_db_backup.sqlBackup all databases
mysqldump -u root -p --all-databases > all_databases_backup.sqlBackup with compression
mysqldump -u root -p company_db | gzip > company_db_backup.sql.gzBackup specific tables
mysqldump -u root -p company_db employees departments > tables_backup.sqlBackup structure only
mysqldump -u root -p --no-data company_db > structure_only.sqlBackup data only
mysqldump -u root -p --no-create-info company_db > data_only.sql`#### Advanced mysqldump Options
| Option | Description | Usage | |--------|-------------|--------| | --single-transaction | Consistent backup for InnoDB | --single-transaction | | --routines | Include stored procedures | --routines | | --triggers | Include triggers | --triggers | | --events | Include scheduled events | --events | | --master-data | Include binary log position | --master-data=2 | | --where | Backup subset of data | --where="date > '2023-01-01'" | | --ignore-table | Skip specific tables | --ignore-table=db.table |
Physical Backups
#### Using mysqlbackup (MySQL Enterprise)
`bash
Full backup
mysqlbackup --user=root --password --backup-dir=/backup/full backupIncremental backup
mysqlbackup --user=root --password --backup-dir=/backup/inc --incremental --start-lsn=LSN backupRestore from backup
mysqlbackup --backup-dir=/backup/full copy-back`#### Using Percona XtraBackup
`bash
Install Percona XtraBackup
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb sudo dpkg -i percona-release_latest.generic_all.deb sudo apt update sudo apt install percona-xtrabackup-80Full backup
xtrabackup --backup --target-dir=/backup/full --user=root --password=passwordPrepare backup
xtrabackup --prepare --target-dir=/backup/fullRestore backup
systemctl stop mysql rm -rf /var/lib/mysql/* xtrabackup --copy-back --target-dir=/backup/full chown -R mysql:mysql /var/lib/mysql systemctl start mysql`Binary Log Backups
#### Configuring Binary Logging
`ini
[mysqld]
Enable binary logging
log-bin = mysql-bin binlog_format = ROW expire_logs_days = 7 max_binlog_size = 100M sync_binlog = 1`#### Managing Binary Logs
`sql
-- Show binary logs
SHOW BINARY LOGS;
-- Show current binary log position SHOW MASTER STATUS;
-- Purge old binary logs PURGE BINARY LOGS TO 'mysql-bin.000010'; PURGE BINARY LOGS BEFORE '2023-01-01 00:00:00';
-- Reset binary logs (use carefully)
RESET MASTER;
`
#### Point-in-Time Recovery
`bash
Extract SQL from binary logs
mysqlbinlog mysql-bin.000001 > binlog_statements.sqlApply binary log to specific point
mysqlbinlog --stop-datetime="2023-12-01 10:30:00" mysql-bin.000001 | mysql -u root -pApply from specific position
mysqlbinlog --start-position=1000 --stop-position=2000 mysql-bin.000001 | mysql -u root -p`Automated Backup Scripts
#### Daily Backup Script
`bash
#!/bin/bash
daily_backup.sh
Configuration
DB_USER="backup_user" DB_PASS="backup_password" BACKUP_DIR="/backups/mysql" DATE=$(date +%Y%m%d_%H%M%S) RETENTION_DAYS=7Create backup directory
mkdir -p $BACKUP_DIRPerform backup
mysqldump -u $DB_USER -p$DB_PASS \ --single-transaction \ --routines \ --triggers \ --all-databases \ --master-data=2 | gzip > $BACKUP_DIR/full_backup_$DATE.sql.gzRemove old backups
find $BACKUP_DIR -name "full_backup_*.sql.gz" -mtime +$RETENTION_DAYS -deleteLog backup completion
echo "$(date): Backup completed successfully" >> /var/log/mysql_backup.log`#### Cron Job Configuration
`bash
Edit crontab
crontab -eAdd daily backup at 2 AM
0 2 * /path/to/daily_backup.shAdd weekly full backup on Sunday at 1 AM
0 1 0 /path/to/weekly_backup.sh`Monitoring and Maintenance
System Monitoring
#### Key Metrics to Monitor
| Metric Category | Metrics | Description | |-----------------|---------|-------------| | Connections | Threads_connected, Max_used_connections | Active connections | | Performance | Questions, Queries per second | Query throughput | | InnoDB | Innodb_buffer_pool_reads, Innodb_buffer_pool_read_requests | Buffer pool efficiency | | Locks | Table_locks_waited, Innodb_row_lock_waits | Lock contention | | Replication | Seconds_behind_master, Slave_lag | Replication health |
#### Monitoring Queries
`sql
-- Connection information
SHOW PROCESSLIST;
SHOW STATUS LIKE 'Threads_%';
SHOW STATUS LIKE 'Max_used_connections';
-- Query performance SHOW STATUS LIKE 'Questions'; SHOW STATUS LIKE 'Slow_queries'; SHOW STATUS LIKE 'Uptime';
-- InnoDB metrics SHOW STATUS LIKE 'Innodb_buffer_pool_%'; SHOW STATUS LIKE 'Innodb_rows_%'; SHOW STATUS LIKE 'Innodb_data_%';
-- Lock information
SHOW STATUS LIKE '%lock%';
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
`
Log Management
#### Error Log Analysis
`bash
View recent errors
tail -f /var/log/mysql/error.logSearch for specific errors
grep -i "error" /var/log/mysql/error.logAnalyze error patterns
awk '/ERROR/ {print $1, $2, $3}' /var/log/mysql/error.log | sort | uniq -c`#### Slow Query Log
`sql
-- Enable slow query log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- View slow query log settings
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
`
#### Analyzing Slow Queries
`bash
Use mysqldumpslow to analyze slow query log
mysqldumpslow -t 10 -s t /var/log/mysql/slow.logSort by query time
mysqldumpslow -s t /var/log/mysql/slow.logSort by count
mysqldumpslow -s c /var/log/mysql/slow.logSort by lock time
mysqldumpslow -s l /var/log/mysql/slow.log`Maintenance Tasks
#### Regular Maintenance Commands
`sql
-- Analyze tables
ANALYZE TABLE employees;
-- Optimize tables OPTIMIZE TABLE employees;
-- Check table integrity CHECK TABLE employees;
-- Repair corrupted tables REPAIR TABLE employees;
-- Update table statistics
ANALYZE TABLE employees UPDATE HISTOGRAM ON salary, department_id;
`
#### Automated Maintenance Script
`bash
#!/bin/bash
maintenance.sh
Configuration
DB_USER="maintenance_user" DB_PASS="maintenance_password" DATABASE="company_db"Get list of tables
TABLES=$(mysql -u $DB_USER -p$DB_PASS -e "USE $DATABASE; SHOW TABLES;" | grep -v Tables_in)Analyze and optimize each table
for table in $TABLES; do echo "Processing table: $table" mysql -u $DB_USER -p$DB_PASS -e "USE $DATABASE; ANALYZE TABLE $table; OPTIMIZE TABLE $table;" doneecho "Maintenance completed at $(date)"
`
Troubleshooting
Common Issues and Solutions
#### Connection Issues
| Issue | Possible Causes | Solutions | |-------|----------------|-----------| | Can't connect to server | Service not running | systemctl start mysql | | Access denied | Wrong credentials | Reset password, check user privileges | | Too many connections | Connection limit reached | Increase max_connections, kill idle connections | | Host not allowed | Host restrictions | Update user host or bind-address |
#### Performance Issues
| Issue | Symptoms | Solutions | |-------|----------|-----------| | Slow queries | High response time | Add indexes, optimize queries | | High CPU usage | Load average > cores | Optimize queries, increase resources | | Memory issues | Swapping, OOM killer | Adjust buffer sizes, add RAM | | Disk I/O bottleneck | High iowait | Use faster storage, optimize queries |
#### Replication Issues
| Issue | Symptoms | Solutions | |-------|----------|-----------| | Slave lag | Seconds_behind_master > 0 | Check network, optimize slave | | Replication stopped | Slave_IO_Running = No | Check connection, restart slave | | Duplicate key errors | Error 1062 | Skip error or fix data inconsistency |
Diagnostic Commands
#### System Information
`sql
-- Show MySQL version
SELECT VERSION();
-- Show system variables SHOW VARIABLES;
-- Show global status SHOW GLOBAL STATUS;
-- Show engine information SHOW ENGINES;
-- Show plugins
SHOW PLUGINS;
`
#### Performance Diagnostics
`sql
-- Show running processes
SHOW PROCESSLIST;
-- Show InnoDB status SHOW ENGINE INNODB STATUS;
-- Show table locks SHOW OPEN TABLES WHERE In_use > 0;
-- Show index usage
SELECT
object_schema,
object_name,
index_name,
count_read,
count_write,
count_fetch,
count_insert,
count_update,
count_delete
FROM performance_schema.table_io_waits_summary_by_index_usage
ORDER BY count_read DESC;
`
Recovery Procedures
#### Recovering from Corruption
`sql
-- Check for corrupted tables
CHECK TABLE table_name;
-- Repair MyISAM tables REPAIR TABLE table_name;
-- For InnoDB corruption
SET GLOBAL innodb_force_recovery = 1;
-- Restart MySQL and dump data
-- Recreate database and restore data
`
#### Emergency Recovery
`bash
Start MySQL in safe mode
mysqld_safe --skip-grant-tables --skip-networking &Reset root password
mysql -u root UPDATE mysql.user SET authentication_string = PASSWORD('newpassword') WHERE User = 'root'; FLUSH PRIVILEGES;Restart MySQL normally
systemctl restart mysql`This comprehensive guide provides a thorough foundation for setting up, configuring, and maintaining MySQL or MariaDB database systems. Regular practice with these commands and concepts will help you become proficient in database administration and troubleshooting.