MySQL Database Instances
Complete guide to creating and managing MySQL database instances on DanubeData.
Overview
MySQL is the world's most popular open-source relational database. DanubeData provides fully managed MySQL instances with:
- Automated backups - Daily backups with 7-day retention
- High availability - Read replicas and failover
- Performance monitoring - Real-time metrics
- Easy scaling - Vertical and horizontal scaling
- Security - Encrypted connections and data
Supported Versions
- MySQL 8.4 - Latest LTS, recommended
- MySQL 8.0 - Previous LTS, stable
Version Selection
MySQL 8.4 (Recommended):
- Latest features
- Best performance
- Active development
- Long-term support
MySQL 8.0:
- Mature and stable
- Wide compatibility
- Extended support
Creating a MySQL Instance
Step-by-Step
- Navigate to Databases in the main menu
- Click Create Database Instance
- Select MySQL as the engine
- Choose version (8.4 recommended)
- Select resource profile
- Configure settings:
- Instance name
- Database name
- Master username
- Master password (auto-generated or custom)
- Region
- Optional: Attach parameter group
- Optional: Attach firewall
- Click Create Database
Configuration Tips
Instance Name:
- Use descriptive names:
prod-mysql-users,staging-mysql-orders - Include environment and purpose
- Use lowercase and hyphens
Database Name:
- Initial database name (default:
danubedata) - Create additional databases later
- Use meaningful names
Master Username:
- Default:
admin - Cannot be
root,mysql, oradminin some versions - Use strong usernames for security
Master Password:
- Auto-generated: Strong, random password
- Custom: Minimum 8 characters, mix of types
- Save it immediately - shown only once!
Connecting to MySQL
Connection Information
After creation, you'll receive:
- Endpoint:
mysql-abc123.danubedata.com - Port:
3306 - Username: Your master username
- Password: Master password (saved during creation)
MySQL Command Line
mysql -h mysql-abc123.danubedata.com \
-P 3306 \
-u admin \
-p
# Enter password when prompted
Connection String
mysql://admin:password@mysql-abc123.danubedata.com:3306/database_name
From Application
PHP (PDO):
<?php
$host = 'mysql-abc123.danubedata.com';
$db = 'database_name';
$user = 'admin';
$pass = 'your_password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset;port=3306";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
Python (mysql-connector):
import mysql.connector
config = {
'host': 'mysql-abc123.danubedata.com',
'port': 3306,
'user': 'admin',
'password': 'your_password',
'database': 'database_name'
}
conn = mysql.connector.connect(**config)
cursor = conn.cursor()
cursor.execute("SELECT VERSION()")
version = cursor.fetchone()
print(f"MySQL version: {version[0]}")
cursor.close()
conn.close()
Node.js (mysql2):
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: 'mysql-abc123.danubedata.com',
port: 3306,
user: 'admin',
password: 'your_password',
database: 'database_name'
});
connection.connect((err) => {
if (err) {
console.error('Error connecting:', err);
return;
}
console.log('Connected to MySQL');
});
// Query
connection.query('SELECT 1 + 1 AS solution', (err, results) => {
if (err) throw err;
console.log('Solution:', results[0].solution);
});
connection.end();
Java (JDBC):
import java.sql.*;
public class MySQLExample {
public static void main(String[] args) {
String url = "jdbc:mysql://mysql-abc123.danubedata.com:3306/database_name";
String user = "admin";
String password = "your_password";
try {
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println("Connected to MySQL");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT VERSION()");
while (rs.next()) {
System.out.println("MySQL version: " + rs.getString(1));
}
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Database Management
Create Databases
-- Create database
CREATE DATABASE myapp_production
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- Use database
USE myapp_production;
-- Show databases
SHOW DATABASES;
-- Drop database
DROP DATABASE old_database;
Create Users
-- Create user
CREATE USER 'appuser'@'%' IDENTIFIED BY 'strong_password';
-- Grant privileges
GRANT ALL PRIVILEGES ON myapp_production.* TO 'appuser'@'%';
-- Grant specific privileges
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_production.* TO 'readonly'@'%';
-- Apply changes
FLUSH PRIVILEGES;
-- Show users
SELECT User, Host FROM mysql.user;
-- Drop user
DROP USER 'olduser'@'%';
Create Tables
-- Create table with InnoDB (default)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_email (email),
INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Show tables
SHOW TABLES;
-- Describe table structure
DESCRIBE users;
-- Show create statement
SHOW CREATE TABLE users;
Performance Optimization
Indexes
-- Add index
CREATE INDEX idx_created_at ON users(created_at);
-- Add composite index
CREATE INDEX idx_status_date ON orders(status, created_at);
-- Add unique index
CREATE UNIQUE INDEX idx_email_unique ON users(email);
-- Show indexes
SHOW INDEX FROM users;
-- Drop index
DROP INDEX idx_old_index ON users;
Query Optimization
-- Explain query plan
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';
-- Analyze table
ANALYZE TABLE users;
-- Optimize table
OPTIMIZE TABLE users;
-- Check table
CHECK TABLE users;
-- Repair table (if needed)
REPAIR TABLE users;
Slow Query Log
-- Enable slow query log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2; -- Queries > 2 seconds
-- Check slow query log status
SHOW VARIABLES LIKE 'slow_query%';
-- View slow queries
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;
Monitoring & Metrics
Key Metrics
Monitor in the dashboard:
- CPU Usage: Database workload
- Memory Usage: Buffer pool and caches
- Connections: Active connections
- Queries/Second: Throughput
- Replication Lag: For replicas
- Slow Queries: Performance issues
Check Status
-- Show status variables
SHOW STATUS LIKE '%connection%';
SHOW STATUS LIKE '%thread%';
SHOW STATUS LIKE '%query%';
-- Show processlist
SHOW FULL PROCESSLIST;
-- Show variables
SHOW VARIABLES LIKE '%max_connections%';
SHOW VARIABLES LIKE '%buffer_pool%';
-- Engine status
SHOW ENGINE INNODB STATUS\G
Performance Schema
-- Enable performance schema
SET GLOBAL performance_schema = ON;
-- Top queries by execution time
SELECT
DIGEST_TEXT,
COUNT_STAR,
AVG_TIMER_WAIT/1000000000000 as avg_time_sec
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC
LIMIT 10;
-- Table I/O
SELECT
OBJECT_NAME,
COUNT_READ,
COUNT_WRITE
FROM performance_schema.table_io_waits_summary_by_table
ORDER BY COUNT_READ + COUNT_WRITE DESC;
Backup & Recovery
Automated Backups
- Frequency: Daily at 2 AM UTC
- Retention: 7 days
- Point-in-time recovery: Yes
- No performance impact: Backups from standby
Manual Snapshots
Create on-demand snapshots:
- Go to database instance page
- Click Snapshots tab
- Click Create Snapshot
- Enter name and description
- Click Create
Export Database
# Export entire database
mysqldump -h mysql-abc123.danubedata.com \
-u admin \
-p \
database_name > backup.sql
# Export specific tables
mysqldump -h mysql-abc123.danubedata.com \
-u admin \
-p \
database_name table1 table2 > tables_backup.sql
# Export with compression
mysqldump -h mysql-abc123.danubedata.com \
-u admin \
-p \
database_name | gzip > backup.sql.gz
# Export structure only (no data)
mysqldump -h mysql-abc123.danubedata.com \
-u admin \
-p \
--no-data \
database_name > structure.sql
Import Database
# Import from backup
mysql -h mysql-abc123.danubedata.com \
-u admin \
-p \
database_name < backup.sql
# Import compressed backup
gunzip < backup.sql.gz | mysql -h mysql-abc123.danubedata.com \
-u admin \
-p \
database_name
Read Replicas
Creating Replicas
- Go to database instance page
- Click Add Replica
- Select node and resource profile
- Click Create Replica
Benefits
- Read Scaling: Offload SELECT queries
- Geographic Distribution: Place replicas near users
- Reporting: Run reports on replica
- Backup Source: Take backups from replica
Using Replicas
Application Configuration:
# Primary (writes)
PRIMARY_DB = {
'host': 'mysql-abc123.danubedata.com',
'port': 3306,
}
# Replica (reads)
REPLICA_DB = {
'host': 'mysql-abc123-replica.danubedata.com',
'port': 3306,
}
# Write to primary
write_conn = connect(PRIMARY_DB)
write_conn.execute("INSERT INTO users ...")
# Read from replica
read_conn = connect(REPLICA_DB)
users = read_conn.execute("SELECT * FROM users").fetchall()
Monitor Replication
-- On replica
SHOW REPLICA STATUS\G
-- Check lag
SELECT
TIMESTAMPDIFF(SECOND, last_applied_time, NOW()) AS lag_seconds
FROM performance_schema.replication_applier_status_by_worker;
Parameter Groups
Customize MySQL configuration:
- Navigate to Parameter Groups
- Click Create Parameter Group
- Select MySQL version
- Configure parameters
- Attach to database instance
Common Parameters
| Parameter | Description | Recommended |
|---|---|---|
max_connections |
Maximum connections | 150-300 |
innodb_buffer_pool_size |
InnoDB cache | 70% of RAM |
query_cache_size |
Query cache | 0 (disabled in 8.0+) |
slow_query_log |
Log slow queries | ON |
long_query_time |
Slow query threshold | 2 seconds |
max_allowed_packet |
Max packet size | 64M |
Security
SSL/TLS Connections
All database instances support encrypted SSL/TLS connections. Use encrypted connections for maximum security.
MySQL CLI with SSL
Modern MySQL clients (5.7.11+) - Simple SSL:
# Encrypted connection (skip hostname verification for internal traffic)
mysql -h mysql-abc123.danubedata.com \
-u admin \
-p \
--ssl-mode=REQUIRED \
--ssl-verify-server-cert=OFF
Modern MySQL clients - Full SSL with Client Certificates:
# Encrypted connection with full certificate authentication
mysql -h mysql-abc123.danubedata.com \
-u admin \
-p \
--ssl-ca=/etc/database-certs/mysql-abc123-ca.pem \
--ssl-cert=/etc/database-certs/mysql-abc123-client-cert.pem \
--ssl-key=/etc/database-certs/mysql-abc123-client-key.pem
Older MySQL clients (pre-5.7.11):
# Encrypted connection (legacy syntax)
mysql -h mysql-abc123.danubedata.com \
-u admin \
-p \
--ssl \
--ssl-verify-server-cert=0
Check your MySQL client version:
mysql --version
Application SSL Connections
PHP (PDO):
$dsn = "mysql:host=mysql-abc123.danubedata.com;port=3306;dbname=mydb";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_SSL_CA => '/etc/database-certs/mysql-abc123-ca.pem',
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false, // Skip hostname verification
];
$pdo = new PDO($dsn, 'admin', $password, $options);
Python (mysql-connector):
import mysql.connector
config = {
'host': 'mysql-abc123.danubedata.com',
'port': 3306,
'user': 'admin',
'password': 'your_password',
'database': 'mydb',
'ssl_ca': '/etc/database-certs/mysql-abc123-ca.pem',
'ssl_verify_cert': True,
'ssl_verify_identity': False # Skip hostname verification
}
conn = mysql.connector.connect(**config)
Node.js (mysql2):
const mysql = require('mysql2');
const fs = require('fs');
const connection = mysql.createConnection({
host: 'mysql-abc123.danubedata.com',
port: 3306,
user: 'admin',
password: 'your_password',
database: 'mydb',
ssl: {
ca: fs.readFileSync('/etc/database-certs/mysql-abc123-ca.pem'),
rejectUnauthorized: false // Skip hostname verification
}
});
Java (JDBC):
String url = "jdbc:mysql://mysql-abc123.danubedata.com:3306/mydb" +
"?useSSL=true" +
"&trustCertificateKeyStoreUrl=file:///etc/database-certs/mysql-abc123-ca.pem" +
"&verifyServerCertificate=false";
Connection conn = DriverManager.getConnection(url, "admin", "password");
Why Skip Hostname Verification?
MySQL auto-generates SSL certificates with generic names that don't match the actual hostname. This causes hostname verification to fail. By skipping hostname verification while still using SSL:
- ✅ Connections are encrypted (TLS/SSL protects data in transit)
- ✅ Safe for internal cluster traffic (Kubernetes NetworkPolicies provide network isolation)
- ✅ Works immediately with auto-generated certificates
- ⚠️ No hostname verification (but MITM attacks are unlikely in private networks)
SSL Certificate Locations
SSL certificates are automatically provisioned to VPS instances:
- CA Certificate:
/etc/database-certs/{database-name}-ca.pem - Client Certificate:
/etc/database-certs/{database-name}-client-cert.pem - Client Key:
/etc/database-certs/{database-name}-client-key.pem
Certificates are automatically extracted when databases start and distributed to all team VPS instances.
Verify SSL Connection
Check that SSL is active:
mysql -h mysql-abc123.danubedata.com -u admin -p \
--ssl-mode=REQUIRED --ssl-verify-server-cert=OFF \
-e "SHOW STATUS LIKE 'Ssl_cipher';"
You should see an SSL cipher like TLS_AES_256_GCM_SHA384.
User Permissions
Follow least privilege:
-- Application user (read/write)
CREATE USER 'app'@'%' IDENTIFIED BY 'strong_pass';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app'@'%';
-- Read-only user (reporting)
CREATE USER 'readonly'@'%' IDENTIFIED BY 'strong_pass';
GRANT SELECT ON mydb.* TO 'readonly'@'%';
-- Admin user (schema changes)
CREATE USER 'dbadmin'@'%' IDENTIFIED BY 'strong_pass';
GRANT ALL PRIVILEGES ON mydb.* TO 'dbadmin'@'%';
FLUSH PRIVILEGES;
Firewall Rules
Restrict database access:
- Create firewall
- Add rules:
- Allow port 3306 from application servers only
- Deny from 0.0.0.0/0
- Attach to database instance
Troubleshooting
Connection Issues
Error: Can't connect:
# Check firewall allows your IP
# Check credentials
# Verify endpoint and port
# Test connection
telnet mysql-abc123.danubedata.com 3306
# Check from application server
mysql -h mysql-abc123.danubedata.com -u admin -p
Error: Too many connections:
-- Check current connections
SHOW PROCESSLIST;
-- Check max connections
SHOW VARIABLES LIKE 'max_connections';
-- Kill idle connections
KILL <process_id>;
-- Increase max_connections in parameter group
Performance Issues
Slow queries:
-- Find slow queries
SELECT * FROM mysql.slow_log ORDER BY query_time DESC LIMIT 10;
-- Missing indexes
SHOW INDEX FROM your_table;
-- Add indexes
CREATE INDEX idx_column ON your_table(column);
High CPU:
- Check for missing indexes
- Optimize queries
- Enable query cache (if MySQL 5.7)
- Consider upgrading instance size
High memory:
- Tune
innodb_buffer_pool_size - Check for memory leaks in queries
- Optimize table structures
Data Issues
Recover deleted data:
- Restore from automated backup
- Restore from snapshot
- Use point-in-time recovery
Table corruption:
CHECK TABLE your_table;
REPAIR TABLE your_table;
Best Practices
Schema Design
- Use InnoDB engine (default)
- Add appropriate indexes
- Use correct data types
- Normalize when needed
- Use foreign keys for referential integrity
Query Optimization
- Use EXPLAIN to analyze queries
- Add indexes for frequent queries
- Avoid SELECT *
- Use LIMIT for large result sets
- Batch INSERT/UPDATE operations
Connection Management
- Use connection pooling
- Close connections when done
- Set appropriate timeouts
- Monitor active connections
Security
- Use strong passwords
- Enable SSL/TLS
- Limit user permissions
- Use firewalls
- Regular security updates
Monitoring
- Monitor key metrics daily
- Set up alerts
- Review slow query log
- Check replication lag
- Monitor disk space
Next Steps
Need help? Contact support through the dashboard.