Skip to content

MySQL 数据库安装规范

系统要求

硬件要求

配置类型CPU内存磁盘网络
开发环境2核4GB50GB1Gbps
测试环境4核8GB100GB1Gbps
生产环境8核+16GB+200GB+ SSD10Gbps

软件要求

软件类型版本要求备注
操作系统CentOS 7.6+ / Ubuntu 18.04+ / RHEL 7.6+推荐使用LTS版本
文件系统XFS / EXT4推荐使用XFS
数据库版本MySQL 8.0+推荐使用官方最新稳定版
依赖库libaio, libnuma, libstdc++安装前需确保已安装

安装前准备

1. 操作系统优化

关闭SELinux

bash
# 临时关闭
setenforce 0

# 永久关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

关闭防火墙(可选)

bash
# CentOS/RHEL
systemctl stop firewalld
systemctl disable firewalld

# Ubuntu
systemctl stop ufw
systemctl disable ufw

配置内核参数

编辑 /etc/sysctl.conf 文件,添加以下参数:

txt
# MySQL 性能优化
fs.file-max = 65535
fs.aio-max-nr = 1048576

# 网络优化
net.core.netdev_max_backlog = 4096
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_fin_timeout = 30

# 内存管理
vm.swappiness = 1
vm.overcommit_memory = 1

# 关闭透明大页
vm.nr_hugepages = 0

应用内核参数:

bash
sysctl -p

关闭透明大页

bash
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 永久关闭,添加到/etc/rc.d/rc.local
cat << EOF >> /etc/rc.d/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
EOF
chmod +x /etc/rc.d/rc.local

配置文件描述符限制

编辑 /etc/security/limits.conf 文件,添加以下内容:

txt
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

2. 磁盘分区规划

挂载点大小文件系统用途
/50GBXFS系统分区
/var/lib/mysql100GB+XFS数据分区
/var/log/mysql50GBXFS日志分区
swap8GB-交换分区

3. 创建MySQL用户和组

bash
# 创建mysql组
groupadd mysql

# 创建mysql用户并加入组
useradd -r -g mysql -s /bin/false mysql

安装步骤

1. 下载MySQL安装包

bash
# 下载MySQL 8.0.30 RPM包(CentOS/RHEL)
wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

# 安装YUM源
sudo rpm -ivh mysql80-community-release-el7-3.noarch.rpm

2. 安装MySQL

CentOS/RHEL

bash
# 安装MySQL服务器
sudo yum install mysql-community-server

Ubuntu

bash
# 更新软件包列表
sudo apt update

# 安装MySQL服务器
sudo apt install mysql-server

3. 启动MySQL服务

bash
# 启动MySQL服务
sudo systemctl start mysqld

# 设置开机自启
sudo systemctl enable mysqld

# 查看MySQL服务状态
sudo systemctl status mysqld

4. 初始化MySQL

获取初始密码

bash
# CentOS/RHEL
sudo grep 'temporary password' /var/log/mysqld.log

# Ubuntu
sudo grep 'password' /var/log/mysql/error.log

安全初始化

bash
# 运行安全初始化脚本
mysql_secure_installation

按照提示完成以下操作:

  1. 输入初始密码
  2. 设置新的root密码
  3. 删除匿名用户
  4. 禁止root远程登录
  5. 删除test数据库
  6. 刷新权限表

配置优化

1. 基础配置

编辑MySQL配置文件 /etc/my.cnf(CentOS/RHEL)或 /etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu),添加以下配置:

ini
# 基本配置
[mysqld]
user = mysql
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid

# 端口配置
port = 3306

# 字符集配置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 日志配置
log-error = /var/log/mysql/error.log
log-bin = /var/log/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 7

# 性能配置
max_connections = 2000
max_connect_errors = 10000
open_files_limit = 65535
table_open_cache = 2048
table_definition_cache = 1024
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
join_buffer_size = 4M

# InnoDB配置
innodb_buffer_pool_size = 8G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_flush_method = O_DIRECT
innodb_large_prefix = ON
innodb_thread_concurrency = 0

2. GTID配置

ini
# GTID配置
gtid_mode = ON
enforce_gtid_consistency = ON

3. 复制配置

ini
# 复制配置
master-info-repository = TABLE
relay-log-info-repository = TABLE
relay-log-recovery = ON
slave-preserve-commit-order = ON
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 4

4. 重启MySQL服务

bash
sudo systemctl restart mysqld

安全设置

1. 创建普通用户

sql
# 登录MySQL
mysql -u root -p

# 创建普通用户
CREATE USER 'admin'@'%' IDENTIFIED BY 'AdminPass123!';

# 授予权限
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;

# 刷新权限
FLUSH PRIVILEGES;

2. 配置防火墙

bash
# 允许MySQL端口
# CentOS/RHEL 7
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload

# Ubuntu
sudo ufw allow 3306/tcp
sudo ufw reload

3. 启用SSL连接

sql
# 登录MySQL
mysql -u root -p

# 生成SSL证书
INSTALL COMPONENT 'file://component_ssl';

# 查看SSL状态
SHOW VARIABLES LIKE '%ssl%';

4. 定期备份

创建备份脚本 backup_mysql.sh

bash
#!/bin/bash

# 备份目录
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份所有数据库
mysqldump -u root -p"password" --all-databases --single-transaction --routines --triggers --events > $BACKUP_DIR/all_databases_$DATE.sql

# 压缩备份文件
gzip $BACKUP_DIR/all_databases_$DATE.sql

# 删除7天前的备份文件
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete

添加到crontab:

bash
# 每天凌晨2点执行备份
0 2 * * * /path/to/backup_mysql.sh

验证安装

1. 验证MySQL服务状态

bash
sudo systemctl status mysqld

2. 验证MySQL版本

bash
mysql --version

3. 验证MySQL连接

bash
# 本地连接
mysql -u root -p

# 远程连接
mysql -u admin -p -h 192.168.1.100

4. 验证数据库状态

sql
# 登录MySQL后执行
SHOW GLOBAL STATUS LIKE 'Uptime';
SHOW DATABASES;

版本差异

MySQL 5.7 vs MySQL 8.0

  1. 默认字符集

    • MySQL 5.7:默认字符集为latin1
    • MySQL 8.0:默认字符集为utf8mb4
  2. 密码验证

    • MySQL 5.7:使用validate_password插件
    • MySQL 8.0:使用validate_password组件,增强了密码强度验证
  3. GTID

    • MySQL 5.7:支持GTID,但默认未启用
    • MySQL 8.0:默认启用GTID
  4. JSON支持

    • MySQL 5.7:基本JSON支持
    • MySQL 8.0:增强的JSON支持,包括JSON路径表达式和JSON聚合函数
  5. 窗口函数

    • MySQL 5.7:不支持窗口函数
    • MySQL 8.0:支持窗口函数
  6. CTE

    • MySQL 5.7:不支持CTE
    • MySQL 8.0:支持CTE

常见问题与解决方案

1. 忘记root密码

解决方案

bash
# 停止MySQL服务
sudo systemctl stop mysqld

# 以跳过授权表模式启动MySQL
sudo mysqld_safe --skip-grant-tables --skip-networking &

# 登录MySQL
mysql -u root

# 重置密码
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPass123!';

# 退出MySQL
exit

# 停止MySQL安全模式进程
sudo pkill mysqld

# 启动MySQL服务
sudo systemctl start mysqld

2. MySQL服务启动失败

解决方案

bash
# 查看错误日志
# CentOS/RHEL
tail -n 100 /var/log/mysqld.log

# Ubuntu
tail -n 100 /var/log/mysql/error.log

根据错误日志提示进行相应的修复,常见问题包括:

  • 权限问题:确保MySQL数据目录权限正确
  • 配置错误:检查配置文件中的语法错误
  • 磁盘空间不足:确保磁盘有足够的空间

3. 无法远程连接MySQL

解决方案

  1. 检查防火墙是否开放3306端口
  2. 检查MySQL用户是否允许远程连接
  3. 检查MySQL配置是否绑定了正确的IP地址
sql
# 允许用户远程连接
CREATE USER 'user'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

4. 数据库连接数过多

解决方案

  1. 增加max_connections参数
  2. 检查应用程序是否存在连接泄漏
  3. 考虑使用连接池
ini
# 在my.cnf中增加
max_connections = 2000

生产环境最佳实践

1. 硬件选择

  • 使用高性能SSD磁盘,提高I/O性能
  • 配置足够的内存,建议将70-80%的内存分配给InnoDB缓冲池
  • 选择多核CPU,提高并发处理能力
  • 使用10Gbps网络,确保数据传输速度

2. 配置管理

  • 使用配置管理工具(如Ansible、Puppet)管理MySQL配置
  • 定期备份配置文件
  • 记录配置变更历史

3. 监控与告警

  • 监控MySQL服务状态、连接数、查询性能等指标
  • 设置告警规则,当指标超过阈值时及时通知
  • 使用专业的监控工具,如Prometheus+Grafana、Zabbix等

4. 定期维护

  • 定期优化表结构
  • 定期更新统计信息
  • 定期检查和修复表
  • 定期清理日志和临时文件

5. 安全管理

  • 定期更新MySQL版本,修复安全漏洞
  • 使用强密码策略
  • 限制用户权限,遵循最小权限原则
  • 定期进行安全审计

常见问题(FAQ)

Q1: MySQL安装时遇到依赖问题怎么办?

A1: 可以使用以下命令安装缺失的依赖:

bash
# CentOS/RHEL
yum install -y libaio libnuma libstdc++

# Ubuntu
apt install -y libaio1 libnuma1 libstdc++6

Q2: 如何修改MySQL数据目录?

A2: 按照以下步骤修改MySQL数据目录:

  1. 停止MySQL服务
  2. 复制数据目录到新位置
  3. 修改配置文件中的datadir参数
  4. 修改目录权限
  5. 启动MySQL服务

Q3: 如何查看MySQL当前配置?

A3: 可以使用以下命令查看MySQL当前配置:

sql
# 查看所有配置变量
SHOW VARIABLES;

# 查看特定配置变量
SHOW VARIABLES LIKE 'max_connections';

Q4: 如何优化MySQL查询性能?

A4: 可以从以下几个方面优化MySQL查询性能:

  1. 为查询字段创建合适的索引
  2. 优化SQL语句,避免全表扫描
  3. 调整MySQL配置参数
  4. 考虑使用缓存
  5. 垂直或水平拆分表

Q5: 如何升级MySQL版本?

A5: 推荐使用滚动升级方式:

  1. 备份数据
  2. 安装新版本MySQL
  3. 测试新版本功能
  4. 逐步迁移数据
  5. 切换到新版本

Q6: 如何监控MySQL复制状态?

A6: 可以使用以下命令监控MySQL复制状态:

sql
# 主库查看二进制日志状态
SHOW MASTER STATUS;

# 从库查看复制状态
SHOW SLAVE STATUS\G;

# 查看复制延迟
SHOW GLOBAL STATUS LIKE 'Seconds_Behind_Master';

Q7: 如何处理MySQL死锁?

A7: 可以使用以下命令查看和处理死锁:

sql
# 查看当前进程
SHOW PROCESSLIST;

# 查看InnoDB状态,包含死锁信息
SHOW ENGINE INNODB STATUS\G;

# 杀死死锁进程
KILL process_id;

Q8: 如何优化InnoDB缓冲池大小?

A8: 建议将InnoDB缓冲池大小设置为系统内存的70-80%:

ini
# 在my.cnf中设置
innodb_buffer_pool_size = 12G

Q9: 如何清理MySQL二进制日志?

A9: 可以使用以下命令清理MySQL二进制日志:

sql
# 清理指定日期之前的日志
PURGE BINARY LOGS BEFORE '2023-01-01 00:00:00';

# 只保留最近7天的日志
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);

Q10: 如何查看MySQL表大小?

A10: 可以使用以下命令查看MySQL表大小:

sql
SELECT 
    table_schema AS '数据库',
    table_name AS '表名',
    ROUND(data_length / 1024 / 1024, 2) AS '数据大小(MB)',
    ROUND(index_length / 1024 / 1024, 2) AS '索引大小(MB)',
    ROUND((data_length + index_length) / 1024 / 1024, 2) AS '总大小(MB)'
FROM information_schema.TABLES 
WHERE table_schema = '数据库名' AND table_name = '表名';