外观
MySQL 8:二进制安装与常用配置
MySQL 的坑集中在初始化前后不能改的参数(lower_case_table_names)、认证插件(caching_sha2_password)和授权范围。
一、二进制安装
bash
yum install -y libaio numactl-libs
# Ubuntu: apt install -y libaio1 libnuma1
cd /usr/local/src
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz
tar xf mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz -C /usr/local
ln -sfn /usr/local/mysql-8.0.40-linux-glibc2.17-x86_64 /usr/local/mysql
/usr/local/mysql/bin/mysqld --versiontext
/usr/local/mysql/bin/mysqld Ver 8.0.40 for Linux on x86_64 (MySQL Community Server - GPL)bash
useradd -r -s /sbin/nologin mysql
mkdir -p /data/mysql/{data,logs,tmp}
chown -R mysql:mysql /data/mysql二、my.cnf
ini
# /etc/my.cnf
[mysqld]
user=mysql
basedir=/usr/local/mysql
datadir=/data/mysql/data
socket=/data/mysql/mysql.sock
pid-file=/data/mysql/mysql.pid
port=3306
bind-address=0.0.0.0
character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci
default-time-zone='+08:00'
# 大小写:只能在初始化前设定
lower_case_table_names=1
max_connections=1000
max_connect_errors=10000
# InnoDB
innodb_buffer_pool_size=4G
innodb_log_file_size=1G
innodb_flush_log_at_trx_commit=1
innodb_flush_method=O_DIRECT
innodb_file_per_table=1
# binlog
server-id=1
log_bin=/data/mysql/logs/binlog
binlog_format=ROW
sync_binlog=1
binlog_expire_logs_seconds=604800
# 慢查询
slow_query_log=1
slow_query_log_file=/data/mysql/logs/slow.log
long_query_time=1
# 错误日志
log_error=/data/mysql/logs/error.log
[client]
socket=/data/mysql/mysql.sock
default-character-set=utf8mb4关键参数解释:
| 参数 | 说明 |
|---|---|
innodb_buffer_pool_size | 通常是物理内存的 50%~70%,是 MySQL 最重要的参数 |
innodb_flush_log_at_trx_commit=1 | 每次提交都 fsync,最安全 |
sync_binlog=1 | 每次提交都刷 binlog,配合上一条保证不丢 |
lower_case_table_names | 必须在 --initialize 之前设置,之后改会启动失败 |
bind-address | 只内网访问时写内网 IP,别图省事写 0.0.0.0 |
innodb_log_file_size | 太小会导致频繁 checkpoint,写性能抖动 |
lower_case_table_names 是单向门
设为 1 后,Table 和 table 视为同一张表。如果先初始化成 0 再改成 1,MySQL 直接拒绝启动:
text
[ERROR] [MY-011087] Different lower_case_table_names settings for server ('1') and data dictionary ('0').只能重新初始化。所以建库前就想好:从 Windows 迁过来的业务通常需要 1。
三、初始化
bash
/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --initialize-insecure --user=mysqltext
2026-10-27T15:12:41.114221Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.40) initializing of server in progress as process 41200
2026-10-27T15:12:58.882004Z 0 [System] [MY-013170] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.0.40) initializing of server has completed--initialize-insecure 生成空密码 root;--initialize 会生成随机密码并打到 error log:
bash
grep 'temporary password' /data/mysql/logs/error.log生产建议用 --initialize,初始化后立刻改密码。
systemd
ini
# /etc/systemd/system/mysqld.service
[Unit]
Description=MySQL Server
After=network-online.target
Wants=network-online.target
[Service]
User=mysql
Group=mysql
Type=notify
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf
ExecReload=/bin/kill -HUP $MAINPID
TimeoutSec=300
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetbash
systemctl daemon-reload
systemctl enable --now mysqld
systemctl status mysqld --no-pagertext
● mysqld.service - MySQL Server
Active: active (running) since Tue 2026-10-27 23:12:58 CST
Status: "Server is operational"四、设置密码与授权
bash
mysql -uroot --socket=/data/mysql/mysql.socksql
ALTER USER 'root'@'localhost' IDENTIFIED BY 'RootPass!2026';远程 root(不建议):
sql
CREATE USER 'root'@'10.0.0.%' IDENTIFIED BY 'RootPass!2026';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.0.0.%' WITH GRANT OPTION;业务账号(推荐最小权限):
sql
CREATE DATABASE shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE USER 'app'@'10.0.0.%' IDENTIFIED BY 'AppPass!2026';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'10.0.0.%';
FLUSH PRIVILEGES;bash
mysql -h 10.0.0.31 -uapp -p -e 'select current_user(), @@hostname;'text
+----------------+------------+
| current_user() | @@hostname |
+----------------+------------+
| app@10.0.0.41 | mysql-1 |
+----------------+------------+'app'@'10.0.0.%' 只允许这个网段,比 'app'@'%' 安全。
caching_sha2_password 与老客户端
MySQL 8 默认认证插件是 caching_sha2_password。老版本 JDBC(5.1.x)会报:
text
java.sql.SQLException: Unable to load authentication plugin 'caching_sha2_password'两种解法:
- 升级驱动到
mysql-connector-java 8.x(推荐)。 - 改用户插件(降低安全性):
sql
ALTER USER 'app'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY 'AppPass!2026';五、常用运维
bash
mysqladmin -uroot -p status
mysqladmin -uroot -p extended-status | grep -E 'Threads_connected|Threads_running|Slow_queries'
mysql -uroot -p -e 'show processlist;'text
Uptime: 86400 Threads: 12 Questions: 1842033 Slow queries: 42 Opens: 1284 Flush tables: 3 Open tables: 512 Queries per second avg: 21.319连接数打满:
sql
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Max_used_connections';
SHOW STATUS LIKE 'Threads_connected';Max_used_connections / max_connections 长期 > 80%,要么加连接数,要么查应用连接池。
六、备份
mysqldump(逻辑备份)
bash
mysqldump -uroot -p \
--single-transaction --quick --routines --triggers --events \
--default-character-set=utf8mb4 \
shop | gzip > /data/backup/shop-$(date +%F-%H%M).sql.gz| 参数 | 作用 |
|---|---|
--single-transaction | InnoDB 一致性快照,不锁表 |
--quick | 边读边写,不把结果集全放内存 |
--routines --triggers --events | 把存储过程/触发器/事件也带上 |
恢复:
bash
gunzip -c shop-2026-10-27-2300.sql.gz | mysql -uroot -p shopxtrabackup(物理备份,大库)
bash
xtrabackup --backup --user=root --password=xxx --target=/data/backup/full
xtrabackup --prepare --target=/data/backup/full
xtrabackup --copy-back --target=/data/backup/full
chown -R mysql:mysql /data/mysql/datamysqldump 不是万能的
- 单表上亿行时极慢,且恢复时间长。
- 备份期间会产生大量 IO,影响业务。
- 默认不含
DEFINER权限相关的兼容性问题。
大库用 xtrabackup 全量 + binlog 增量,并定期做恢复演练。
七、慢查询
ini
slow_query_log=1
long_query_time=1
slow_query_log_file=/data/mysql/logs/slow.logbash
mysqldumpslow -s t -t 10 /data/mysql/logs/slow.logtext
Count: 128 Time=3.42s (437s) Lock=0.00s (0s) Rows=1842.0 (235776), app[app]@2 hosts
SELECT * FROM orders WHERE user_id = N AND status = 'N' ORDER BY created_at DESC LIMIT N-s t 按总耗时排序,-t 10 取前 10。
在线看:
sql
SELECT * FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC LIMIT 10\G八、常见错误
| 错误 | 原因 | 处置 |
|---|---|---|
1045 Access denied | 密码错 / 用户 host 不匹配 | SELECT user,host FROM mysql.user |
1130 Host is not allowed | 用户没有该来源的 host 授权 | 建 'user'@'网段' |
2002 Can't connect to local MySQL through socket | socket 路径不一致 | 客户端加 --socket= |
2003 Can't connect to MySQL server | 端口/防火墙/bind-address | ss -lntp、telnet 端口 |
1040 Too many connections | 连接打满 | 调大 max_connections,查连接池 |
1071 Specified key was too long | 索引长度超限 | 缩短索引,或用前缀索引 |
1366 Incorrect string value | 字符集不是 utf8mb4 | 库/表/连接三处统一 |
1055 ONLY_FULL_GROUP_BY | SQL 不合规 | 改写 SQL,别关 sql_mode |
ERROR 1118 Row size too large | 行太大 | 改 TEXT/BLOB,调 innodb_page_size |
启动报 lower_case_table_names 不一致 | 初始化后改了这个参数 | 只能重新初始化 |
九、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
初始化后改 lower_case_table_names 起不来 | 单向门 | 重新初始化 |
| 中文乱码 | 字符集/排序规则不一致 | 库、表、连接、客户端四处统一 utf8mb4 |
| 时间差 8 小时 | default-time-zone 未设 | 设 '+08:00' 或 time_zone 表 |
| 磁盘涨得飞快 | binlog 没设过期 | binlog_expire_logs_seconds |
| 主从延迟 | sync_binlog=1 + 大事务 | 拆小事务,开并行复制 |
| 重启后表名大小写变了 | lower_case_table_names 与初始化不一致 | 重建实例 |
| 备份恢复后权限丢失 | 用 --single-transaction 但没带 --routines | 补齐参数 |
| 连接数上不去 | max_connections 与 open_files_limit 联动 | 同时调 LimitNOFILE |