在 2核 2GB 内存的服务器上运行 Spring Boot + MySQL,资源非常紧张。MySQL 默认配置是为更大服务器设计的,直接启动极易导致 OOM(内存溢出) 或 Swap 交换频繁导致性能骤降。
以下是针对该环境的关键优化参数及建议,分为 MySQL 服务端优化、JVM/Spring Boot 优化 和 架构/应用层优化 三部分:
✅ 一、MySQL 服务端优化(核心重点)
📌 1. 修改 my.cnf / my.ini 关键参数
[mysqld]
# 基础设置
port = 3306
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
# 内存相关(最关键!)
innodb_buffer_pool_size = 512M # ⚠️ 最大不超过物理内存的 50%,留足 OS 和其他进程空间
innodb_log_file_size = 128M # 减少刷盘频率,提升写入性能
innodb_flush_log_at_trx_commit = 1 # 保持 ACID,若可接受少量数据丢失可改为 2
# 连接与线程
max_connections = 100 # 根据实际并发调整,避免过多连接占用内存
thread_cache_size = 8 # 缓存线程,减少创建开销
table_open_cache = 400 # 表描述符缓存,适当调高
# 查询缓存(MySQL 5.7+ 已移除,8.0 默认关闭)
query_cache_type = 0 # 强制关闭,现代 MySQL 不推荐启用
# InnoDB 其他优化
innodb_flush_method = O_DIRECT # 避免双重缓冲,提升 I/O 效率
innodb_io_capacity = 200 # 根据磁盘类型调整(SSD 可设为 1000+)
innodb_read_io_threads = 4
innodb_write_io_threads = 4
# 日志与监控
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
💡 为什么
innodb_buffer_pool_size设为 512M?
2GB 服务器中,OS 需要 ~300–500MB,Java JVM 需要 ~512MB–1GB,MySQL 其他组件也需要内存。留给 InnoDB 缓冲池 512MB–768MB 是安全上限。超过此值极易触发 Swap 或 OOM。
📌 2. 禁用不必要的功能
- 关闭二进制日志(若非主从复制需求):
log_bin = OFF binlog_format = ROW expire_logs_days = 0 max_binlog_size = 0 - 关闭性能模式(Performance Schema)在生产环境:
performance_schema = OFF
✅ 二、Spring Boot / JVM 优化
📌 1. JVM 参数优化(通过 application.yml 或启动脚本)
java -jar app.jar
-Xms512m
-Xmx512m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/java/heapdump.hprof
-Xms512m -Xmx512m:固定堆大小,避免动态伸缩带来 GC 压力。- G1 GC:适合中等堆内存,暂停时间可控。
- 若使用 Java 17+,可考虑 ZGC(但需测试兼容性)。
📌 2. Spring Boot 配置优化
spring:
datasource:
hikari:
maximum-pool-size: 10 # 连接池大小,根据 CPU 核数 * 2 + 有效磁盘数 估算
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
leak-detection-threshold: 60000 # 检测连接泄漏
jpa:
hibernate:
ddl-auto: update # 生产环境建议用 Flyway/Liquibase
properties:
hibernate:
jdbc:
batch_size: 50 # 批量插入优化
order_inserts: true
order_updates: true
cache:
use_second_level_cache: false # 小项目不建议开启二级缓存
use_query_cache: false
💡 HikariCP 连接池大小公式参考:
CPU 核数 * 2 + 磁盘有效数→ 2*2 + 1 = 5,保守设 8–10。
✅ 三、应用层与架构优化
📌 1. 数据库层面
- 索引优化:确保高频查询有合适索引,避免全表扫描。
- 分页限制:
LIMIT不要过大,超过 1000 条建议使用游标分页或 ID 范围查询。 - 避免大事务:长事务会持有锁和缓冲页,加剧内存压力。
- 定期清理慢查询日志,分析并优化 SQL。
📌 2. 缓存策略
- 本地缓存:使用 Caffeine 缓存热点数据(如字典、配置),减少 DB 访问。
- Redis 缓存:若可能,将 Redis 部署在另一台机器或使用云 Redis,减轻本机压力。
- 示例 Caffeine 配置:
spring: cache: type: caffeine caffeine: spec: maximumSize=500,expireAfterWrite=10m
📌 3. 监控与告警
- 启用 Actuator 端点
/metrics、/health。 - 使用 Prometheus + Grafana 监控 JVM、MySQL QPS、连接数、Buffer Pool 命中率等。
- 设置内存使用率 >80% 时告警。
✅ 四、额外建议
| 项目 | 建议 |
|---|---|
| 操作系统 | 使用 Ubuntu/CentOS 最小化安装,关闭非必要服务 |
| Swap | 尽量禁用 Swap(vm.swappiness=0),避免性能抖动 |
| 文件系统 | 使用 ext4/xfs,挂载选项加 noatime 减少 I/O |
| 备份策略 | 使用 mysqldump 或 Percona XtraBackup,避免高峰备份 |
| 容器化 | 若用 Docker,限制 MySQL 容器内存上限:--memory=1g |
✅ 总结检查清单
✅ innodb_buffer_pool_size = 512M
✅ JVM 堆内存 ≤ 512MB
✅ HikariCP 连接池 ≤ 10
✅ 关闭二进制日志、性能模式
✅ 启用 G1 GC,固定堆大小
✅ 添加必要索引,避免 N+1 查询
✅ 使用本地缓存减少 DB 压力
✅ 监控内存、QPS、慢查询
如后续业务增长,建议:
- 垂直扩展:升级至 4核 4GB 以上
- 水平拆分:MySQL 读写分离,或迁移至云数据库 RDS
- 引入缓存中间件:Redis 独立部署
希望这些优化能帮助你在有限资源下稳定运行!如需具体 SQL 优化或监控配置,可提供更多细节继续深入。
云知识CLOUD