Linux MySQL 数据库部署与优化

1次阅读

mysql服务启动失败主因是配置文件语法错误或数据目录权限问题,需检查my.cnf语法、/var/lib/mysql权限及初始化状态;批量插入宜控制在500–1000行/语句并配合事务;json字段查询需用生成列+索引;mysqldump恢复大库应延迟建索引。

Linux MySQL 数据库部署与优化

MySQL 服务起不来,systemctl status mysql 显示 Failed to start MySQL Server

常见原因是配置文件语法错误或数据目录权限不对,不是磁盘满或端口冲突(那些会报更具体的错)。先看日志:sudo journalctl -u mysql -n 50 --no-pager,重点找 mysqld: Can't read dir of '/etc/mysql/conf.d/'Can't open the mysql.plugin table 这类提示。

实操建议:

  • 检查 /etc/mysql/my.cnf/etc/mysql/conf.d/*.cnf 是否有重复 [mysqld] 段、未闭合引号、中文字符——MySQL 配置不支持 UTF-8 bom 和注释后空格
  • 确认 /var/lib/mysql 所有者是 mysql:mysqlsudo chown -R mysql:mysql /var/lib/mysql,尤其重装后容易漏这步
  • 如果用 mysqld --initialize 初始化过,但没保存生成的临时密码,就别硬启服务,先删掉 /var/lib/mysql 重来,否则卡在 Starting authentication plugin 'caching_sha2_password'

插入大量数据时 INSERT ... VALUES (...), (...), (...) 很慢

单条语句插 100 行比 100 条单行 INSERT 快,但超过 1000 行后性能反而下降,还容易触发 max_allowed_packet 超限。这不是 SQL 写法问题,是协议层和 InnoDB 日志刷写机制共同作用的结果。

实操建议:

  • 批量插入控制在 500–1000 行/语句,用 INSERT INTO t (a,b) VALUES (1,2), (3,4), ..., (999,1000)
  • 插入前加 SET autocommit=0; START TRANSACTION;,所有批次插完再 COMMIT;,避免每条都刷 redo log
  • 临时调大 innodb_log_file_size(需停库)和 innodb_buffer_pool_size(动态可调),但别设到物理内存 80% 以上,留内存给 OS 缓存

select * FROM t WHERE json_col->"$.name" = "foo" 查询不走索引

MySQL 5.7+ 支持 JSON 字段路径查询,但 -> 操作符本身不触发索引,必须配合生成列 + 索引。直接在 JSON 字段上建索引会报错:Error 3152 (HY000): A generated column cannot be indexed unless it is STORED

实操建议:

  • 先加生成列:ALTER TABLE t ADD COLUMN name_str VARCHAR(64) AS (json_col->>"$.name") STORED;
  • 再建索引:CREATE INDEX idx_name_str ON t (name_str);
  • 查询改用生成列:SELECT * FROM t WHERE name_str = "foo";,别再用 json_col->"$.name"
  • 注意 -> 返回带引号字符串->> 去引号——生成列必须用 ->>,否则索引值含双引号,查不到

mysqldump 恢复大库时卡在 Creating index ...

默认 mysqldump 输出包含 CREATE INDEX 语句,恢复时每建一个索引都要全表扫描排序,IO 和 CPU 双高。10GB 以上的库可能卡几小时,不是网络或磁盘慢,是 MySQL 在“边建索引边写数据”。

实操建议:

  • 导出时加 --skip-opt --extended-insert --no-create-info,再单独导结构:mysqldump -d db > schema.sql
  • 恢复时先关索引:SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;,导入数据后再 source schema.sql
  • 如果用 mysqlpump(MySQL 5.7+),加 --defer-table-indexes 参数,它会自动把索引创建挪到最后

真正麻烦的是 JSON 字段里嵌套深、字符集混用、或者用了 utf8mb4_0900_as_cs 这种新 collation 却没同步客户端设置——这些不会报错,但查出来字段乱码或 NULL,得翻 SHOW CREATE TABLESELECT CHARSET(json_col), COLLATION(json_col) 对着看。

text=ZqhQzanResources