MySQL 安装与配置
大约 11 分钟约 3406 字
MySQL 安装与配置
简介
MySQL 是最常见的关系型数据库之一,既适合中小型业务系统,也广泛用于企业后台、报表平台和互联网服务。真正落地时,安装只是第一步,更重要的是把数据目录、字符集、账户权限、远程访问、日志、备份和性能参数组织成一套稳定可维护的运行方式。
特点
实现
安装前准备与环境检查
# 检查系统已有 MariaDB / MySQL 组件
rpm -qa | grep -i maria
rpm -qa | grep -i mysql
# 如有冲突包先清理
yum remove -y mariadb-libs.x86_64# 检查磁盘、内存和端口
lsblk
free -m
ss -lntp | grep 3306环境检查详解
# ====== 系统版本检查 ======
cat /etc/redhat-release
uname -r
# ====== 已安装的数据库组件检查 ======
rpm -qa | grep -i maria
rpm -qa | grep -i mysql
# 如有冲突包先清理(CentOS 7 默认安装 MariaDB)
yum remove -y mariadb-libs mariadb-server mariadb
# ====== 资源检查 ======
# 检查磁盘空间(建议数据目录至少 50GB)
df -h
# 检查内存(MySQL 建议至少 2GB)
free -m
# 检查端口占用
ss -tlnp | grep 3306
# 检查系统限制
ulimit -n
cat /etc/security/limits.conf | grep mysql
# ====== 系统参数配置 ======
# 增加文件描述符限制
cat >> /etc/security/limits.conf << 'EOF'
mysql soft nofile 65535
mysql hard nofile 65535
EOF
# 增加虚拟内存
echo 'vm.swappiness=1' >> /etc/sysctl.conf
sysctl -p
# ====== 安装依赖 ======
yum install -y libaio ncurses-devel cmake gcc gcc-c++ make安装前至少确认:
- 数据目录放哪里
- 是否需要远程访问
- 字符集统一用什么
- root 管理方式是什么
- 后续如何备份和监控安装 MySQL(通用二进制包思路)
# 下载(示意版本)
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
# 解压到 /opt
tar -xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz -C /opt
mv /opt/mysql-8.0.36-linux-glibc2.28-x86_64 /opt/mysql安装方式对比
# ====== 方法 1:二进制包安装(推荐,灵活控制版本和路径) ======
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
tar -xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz -C /opt
mv /opt/mysql-8.0.36-linux-glibc2.28-x86_64 /opt/mysql
# ====== 方法 2:YUM 仓库安装(简单但不一定最新) ======
# 添加 MySQL 官方仓库
yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
yum install -y mysql-community-server
# 安装指定版本
yum install -y mysql-community-server-8.0.36-1.el7
# 查看可用版本
yum list available --showduplicates mysql-community-server
# ====== 方法 3:源码编译(最灵活,耗时长) ======
yum install -y cmake gcc gcc-c++ ncurses-devel bison
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36.tar.gz
tar -zxf mysql-8.0.36.tar.gz -C /usr/local/src
cd /usr/local/src/mysql-8.0.36
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_FEDERATED_STORAGE_ENGINE=1 \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DWITH_BOOST=OFF
make -j$(nproc)
make install# 创建用户和组
groupadd mysql
useradd -r -g mysql -s /sbin/nologin mysql# 创建数据目录并授权
mkdir -p /data/mysql
chown -R mysql:mysql /opt/mysql /data/mysql# 初始化数据库(会生成临时 root 密码)
cd /opt/mysql/bin
./mysqld --initialize --user=mysql --basedir=/opt/mysql --datadir=/data/mysql
# 找临时密码
grep 'temporary password' /data/mysql/*.err初始化详解
# ====== MySQL 8.0 初始化 ======
cd /opt/mysql/bin
# 基本初始化
./mysqld --initialize --user=mysql \
--basedir=/opt/mysql \
--datadir=/data/mysql
# 初始化并指定临时 root 密码(推荐)
./mysqld --initialize --user=mysql \
--basedir=/opt/mysql \
--datadir=/data/mysql \
--initialize-insecure
# 查看临时密码(如果使用了默认初始化)
grep 'temporary password' /data/mysql/*.err
# 输出示例:[Note] A temporary password is generated for root@localhost: Abcdef1!
# MySQL 5.7 初始化(旧版本)
# ./mysql_install_db --user=mysql --basedir=/opt/mysql --datadir=/data/mysql
# ====== 安全初始化(MySQL 8.0) ======
# 初始化后使用 mysql_secure_installation 进行安全配置
/opt/mysql/bin/mysql_secure_installation \
--user=mysql \
--basedir=/opt/mysql \
--datadir=/data/mysql
# 交互式安全配置:
# 1. 设置 root 密码
# 2. 移除匿名用户
# 3. 禁止 root 远程登录
# 4. 删除测试数据库
# 5. 重新加载权限表基础配置文件
# /etc/my.cnf
[client]
default-character-set = utf8mb4
port = 3306
socket = /tmp/mysql.sock
[mysqld]
user = mysql
port = 3306
basedir = /opt/mysql
datadir = /data/mysql
socket = /tmp/mysql.sock
pid-file = /data/mysql/mysql.pid
bind-address = 0.0.0.0
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
max_connections = 300
max_allowed_packet = 64M
log_error = /data/mysql/error.log
slow_query_log = 1
slow_query_log_file = /data/mysql/slow.log
long_query_time = 2
default_storage_engine = InnoDB
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION生产级配置文件
# /etc/my.cnf - 生产环境推荐配置
[client]
default-character-set = utf8mb4
port = 3306
socket = /tmp/mysql.sock
# 自动补全
no-auto-rehash
[mysql]
default-character-set = utf8mb4
[mysqld]
user = mysql
port = 3306
basedir = /opt/mysql
datadir = /data/mysql
socket = /tmp/mysql.sock
pid-file = /data/mysql/mysql.pid
# ====== 网络配置 ======
bind-address = 0.0.0.0
skip-name-resolve = 0
max_connections = 500
max_connect_errors = 1000
max_allowed_packet = 64M
thread_cache_size = 64
wait_timeout = 600
interactive_timeout = 600
# ====== 字符集配置 ======
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
init_connect = 'SET NAMES utf8mb4'
character-set-client-handshake = FALSE
skip-character-set-client-handshake = TRUE
# ====== InnoDB 配置 ======
default-storage-engine = InnoDB
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 4
innodb_log_file_size = 512M
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = ON
innodb_lock_wait_timeout = 30
innodb_deadlock_detect = ON
innodb_file_per_table = ON
# ====== 日志配置 ======
log_error = /data/mysql/error.log
slow_query_log = 1
slow_query_log_file = /data/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = ON
log_throttle_queries_not_using_indexes = 60
log_error_verbosity = 2
# ====== Binlog 配置(主从复制需要) ======
log-bin = mysql-bin
binlog_format = ROW
binlog_cache_size = 4M
max_binlog_size = 256M
expire_logs_days = 7
sync_binlog = 0
binlog_row_image = FULL
# ====== SQL 模式 ======
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
explicit_defaults_for_timestamp = TRUE
# ====== 安全配置 ======
local_infile = OFF
skip-symbolic-links = FALSE
skip-name-resolve = 0
# ====== 临时表和排序 ======
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
# ====== 服务器ID(主从复制需要) ======
server-id = 1
# ====== 时区 ======
default-time-zone = '+08:00'# 可选:加入 PATH
echo 'export PATH=$PATH:/opt/mysql/bin' >> /etc/profile
source /etc/profile
# 或者创建全局环境变量文件
cat > /etc/profile.d/mysql.sh << 'EOF'
export PATH=$PATH:/opt/mysql/bin
export MYSQL_HOME=/opt/mysql
EOF
chmod +x /etc/profile.d/mysql.sh
source /etc/profile.d/mysql.sh建议尽量统一:
- utf8mb4 字符集
- InnoDB 存储引擎
- 慢查询日志默认开启
- 数据目录与安装目录分离启动服务与 systemd 管理
# /etc/systemd/system/mysql.service
[Unit]
Description=MySQL Server
After=network.target
[Service]
User=mysql
Group=mysql
Type=forking
ExecStart=/opt/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf
ExecStop=/opt/mysql/bin/mysqladmin shutdown -uroot -p
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetSystemd 服务管理详解
# ====== 服务管理 ======
systemctl daemon-reload
systemctl enable --now mysql
systemctl status mysql
systemctl start mysql
systemctl stop mysql
systemctl restart mysql
# ====== 查看日志 ======
journalctl -u mysql -f
journalctl -u mysql --since "1 hour ago"
# ====== 验证服务 ======
mysql -uroot -p -S /tmp/mysql.sock
mysqladmin -uroot -p -S /tmp/mysql.sock status
mysqladmin -uroot -p -S /tmp/mysql.sock ping初始化安全与用户管理
-- 修改 root 密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewStrongPassword123!';
FLUSH PRIVILEGES;安全配置详解
-- ====== MySQL 8.0 密码管理 ======
-- 修改 root 密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPass2024!';
FLUSH PRIVILEGES;
-- MySQL 8.0 密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- validate_password.policy: 密码强度策略(LOW/MEDIUM/STRONG)
-- validate_password.length: 最小密码长度
-- validate_password.mixed_case_count: 大写字母数量
-- validate_password.number_count: 数字数量
-- validate_password.special_char_count: 特殊字符数量
-- 调整密码策略(生产环境建议 MEDIUM 或 STRONG)
SET GLOBAL validate_password.policy = MEDIUM;
SET GLOBAL validate_password.length = 12;
-- 修改密码过期策略
SET GLOBAL default_password_lifetime = 90;
-- ====== 创建业务用户 ======
-- 创建数据库
CREATE DATABASE appdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE DATABASE logdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 创建只读用户
CREATE USER 'reader'@'%' IDENTIFIED BY 'ReaderPass2024!';
GRANT SELECT ON appdb.* TO 'reader'@'%';
GRANT SELECT ON logdb.* TO 'reader'@'%';
FLUSH PRIVILEGES;
-- 创建读写用户
CREATE USER 'appuser'@'%' IDENTIFIED BY 'AppUserPass2024!';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'%';
GRANT SELECT ON logdb.* TO 'appuser@'%';
FLUSH PRIVILEGES;
-- 创建管理员用户
CREATE USER 'dbadmin'@'%' IDENTIFIED BY 'DBAdminPass2024!';
GRANT ALL PRIVILEGES ON *.* TO 'dbadmin'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
-- 限制用户只能从特定 IP 访问
CREATE USER 'appuser'@'192.168.1.%' IDENTIFIED BY 'AppUserPass2024!';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'192.168.1.%';
FLUSH PRIVILEGES;
-- ====== 查看用户与权限 ======
SELECT User, Host, authentication_string FROM mysql.user;
SELECT User, Host FROM mysql.user;
SHOW GRANTS FOR 'appuser'@'%';
SHOW GRANTS FOR 'dbadmin'@'%';
-- ====== 修改用户密码 ======
ALTER USER 'appuser'@'%' IDENTIFIED BY 'NewAppUserPass2024!';
FLUSH PRIVILEGES;
-- ====== 删除用户 ======
DROP USER 'reader'@'%';
FLUSH PRIVILEGES;
-- ====== 撤销权限 ======
REVOKE ALL PRIVILEGES ON appdb.* FROM 'appuser'@'%';
REVOKE SELECT ON logdb.* FROM 'appuser@'%';
FLUSH PRIVILEGES;
-- ====== 删除匿名用户和测试数据库 ======
DELETE FROM mysql.user WHERE user='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE db='test' OR db='test_%';
FLUSH PRIVILEGES;生产建议:
- 不要长期使用 root 跑业务连接
- root 只保留本地管理用途
- 业务账号按库 / 按权限最小化授权防火墙与远程访问
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-ports远程访问配置
# ====== 防火墙配置 ======
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload
# 限制来源 IP
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept'
firewall-cmd --reload
# ====== 远程连接测试 ======
# 从远程机器连接
mysql -h 192.168.1.10 -P 3306 -u appuser -p'AppUserPass2024!'
# 使用 SSL 连接(推荐生产环境)
# mysql --ssl-ca=/etc/mysql/ca.pem --ssl-cert=/etc/mysql/client-cert.pem --ssl-key=/etc/mysql/client-key.pem -h 192.168.1.10 -u appuser -p'AppUserPass2024!'远程访问失败时,优先检查:
- bind-address
- 防火墙
- 用户 host 范围
- 云厂商安全组常见运维操作
-- 查看数据库
SHOW DATABASES;
-- 查看表
USE appdb;
SHOW TABLES;
-- 查看当前连接数
SHOW STATUS LIKE 'Threads_connected';
-- 查看慢查询是否开启
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';运维操作详解
-- ====== 数据库管理 ======
SHOW DATABASES;
CREATE DATABASE newdb CHARACTER SET utf8mb4;
DROP DATABASE olddb;
USE appdb;
-- ====== 表管理 ======
SHOW TABLES;
SHOW CREATE TABLE users;
DESCRIBE users;
SHOW TABLE STATUS LIKE 'users';
SHOW INDEX FROM users;
-- ====== 连接管理 ======
SHOW PROCESSLIST;
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';
KILL 1234; -- 杀掉指定连接
-- ====== 变量查看 ======
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW GLOBAL STATUS LIKE 'Slow_queries';
SHOW GLOBAL STATUS LIKE 'Questions';
SHOW GLOBAL STATUS LIKE 'Com_commit';
SHOW GLOBAL STATUS LIKE 'Com_rollback';
-- ====== 存储引擎信息 ======
SHOW ENGINES;
SHOW ENGINE INNODB STATUS;
-- ====== InnoDB 状态 ======
SHOW ENGINE INNODB STATUS\G;# ====== 日志管理 ======
# 查看错误日志
tail -f /data/mysql/error.log
# 查看慢查询日志
tail -f /data/mysql/slow.log
# 查看通用查询日志
tail -f /data/mysql/mysql.log
# 按条件搜索日志
grep "ERROR" /data/mysql/error.log | tail -20
grep "Access denied" /data/mysql/error.log
# ====== 磁盘空间管理 ======
# 查看各数据库大小
mysql -uroot -p -e "SELECT table_schema AS 'Database', ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)' FROM information_schema.tables GROUP BY table_schema ORDER BY 2 DESC;"
# 查看各表大小
mysql -uroot -p -e "SELECT table_schema, table_name, ROUND((data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)' FROM information_schema.tables WHERE table_schema = 'appdb' ORDER BY 2 DESC;"
# ====== 逻辑备份示例 ======
mysqldump -uroot -p --single-transaction --databases appdb > /backup/appdb_$(date +%F).sql备份与恢复详解
# ====== mysqldump 备份 ======
# 备份单个数据库
mysqldump -uroot -p --single-transaction --routines --triggers appdb > /backup/appdb_$(date +%Y%m%d).sql
# 备份所有数据库
mysqldump -uroot -p --all-databases --single-transaction --routines --triggers > /backup/all_$(date +%Y%m%d).sql
# 只备份表结构
mysqldump -uroot -p --no-data appdb > /backup/appdb_schema.sql
# 备份指定表
mysqldump -uroot -p appdb users orders > /backup/appdb_tables.sql
# 压缩备份
mysqldump -uroot -p appdb | gzip > /backup/appdb_$(date +%Y%m%d).sql.gz
# ====== 恢复 ======
# 恢复数据库
mysql -uroot -p < /backup/appdb_20240101.sql
# 恢复到指定数据库
mysql -uroot -p appdb < /backup/appdb_20240101.sql
# 恢复压缩备份
gunzip < /backup/appdb_20240101.sql.gz | mysql -uroot -p appdb
# ====== 自动备份脚本 ======
#!/bin/bash
# mysql_backup.sh
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DATABASES="appdb logdb"
RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR"
for db in $DATABASES; do
mysqldump -uroot -p --single-transaction --routines --triggers \
"$db" 2>/dev/null | gzip > "${BACKUP_DIR}/${db}_${DATE}.sql.gz"
done
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: ${BACKUP_DIR}/*_${DATE}.sql.gz"
# Crontab 配置(每天凌晨 2 点执行)
# 0 2 * * * /usr/local/bin/mysql_backup.sh优点
缺点
总结
MySQL 安装真正有价值的部分,不是把服务拉起来,而是把配置、账户、安全、日志和备份一起设计成可长期维护的状态。对生产环境来说,最重要的不是"能连上",而是"出了问题能查、能恢复、能控风险"。
关键知识点
- 数据目录和安装目录要尽量分离。
- 统一字符集通常优先选择 utf8mb4。
- root 账户不应该直接作为业务账户使用。
- 慢查询日志和错误日志是最基础的排障抓手。
- innodb_buffer_pool_size 建议设为物理内存的 50%-70%。
- MySQL 8.0 默认认证插件为 caching_sha2_password,部分客户端需要调整。
- binlog_format=ROW 是主从复制的推荐格式。
项目落地视角
- 小型项目至少要有:强密码、独立业务用户、备份脚本、慢查询日志。
- 中型项目通常会继续引入主从、监控、读写分离和定期演练恢复。
- 容器化环境里也要重点考虑卷挂载、配置注入和恢复策略。
- 多环境部署时要明确区分开发、测试、生产的连接和权限边界。
常见误区
- 直接开放 root 远程访问,且密码过弱。
- 只安装不做备份和恢复验证。
- 配置字符集混乱,后期数据乱码难以收拾。
- 遇到性能问题只会调参数,不先看索引和 SQL。
- 不配置 binlog 导致无法做主从复制和增量恢复。
进阶路线
- 学习主从复制、读写分离和高可用方案。
- 深入理解 InnoDB、事务隔离级别和锁。
- 建立慢查询分析、容量规划和监控告警体系。
- 结合 Docker / Kubernetes 做容器化数据库治理。
适用场景
- Web 应用和后台业务系统。
- 关系型数据存储。
- 需要事务支持的订单、用户、内容、权限系统。
- 中小到中大型企业业务数据库场景。
落地建议
- 统一 MySQL 版本、字符集、目录结构和账户规范。
- 所有环境都建立最小备份与恢复机制。
- 默认开启慢查询日志,并定期分析。
- 把数据库安装文档升级为"安装 + 配置 + 排障 + 回滚"模板。
排错清单
- 启动失败:先看 error.log。
- 连不上:看监听地址、端口、防火墙、用户 host 范围。
- 登录失败:看密码策略和用户授权。
- 性能差:先看慢查询、索引和磁盘,再看参数。
