表设计优化
-
数据类型选择:使用最小合适的数据类型(比如使用
INT代替VARCHAR存储 IP)。 -
尽量避免使用
ENUM,优先使用VARCHAR或TINYINT + 字典表的方式。因为增加新枚举值需ALTER TABLE,在大表上会锁表,影响线上服务。且ENUM排序时是按"内部数字"而非字母顺序,使用起来容易出错。 -
选择合适的字符存储长度:不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
-
拆分大字段和访问频率低的字段,分离冷热数据。
-
大字段拆分:将
BLOB、TEXT等大字段拆分到独立表,减少主表 I/O。 -
不在数据库中存储图片、文件等大数据。大文件和图片应存储在文件系统。
-
尽可能把所有列定义为
NOT NULL(需要根据实际应用情况)。因为NULL值在索引中需要额外存储和处理(使用 null bits 位图),并且涉及NULL的表达式计算更复杂,可能导致索引失效。 -
使用
TIMESTAMP(4个字节)或DATETIME(8个字节)存储时间,而不是使用字符串(占用更多存储空间,且无法使用日期函数进行计算和比较)。 -
存储引擎选择:优先使用 InnoDB(支持事务、行级锁、崩溃恢复)。MyISAM 适用于读多写少的场景,但不支持事务。
-
反范式化:适当冗余字段(如省市县)以减少 JOIN 操作。
-
谨慎使用分区表:分区表在物理上表现为多个文件,在逻辑上表现为一个表,跨分区查询效率低,建议采用物理分表的方式管理大数据。
-
单表列数目最好小于 50,超出的话建议考虑垂直分表。
-
每张表数据量建议控制在 500w 以下,超过 500w 可以使用历史数据归档或分库分表来实现(500万行并不是 MySQL 数据库的限制,只是单表过大对于修改表结构,备份,恢复都会有很大问题)。
-
禁止在表中建立预留字段。预留字段的命名很难做到见名识义,预留字段无法确认存储的数据类型,所以无法选择合适的类型;对预留字段类型的修改,会对表进行锁定。
SQL优化
- 开启慢日志分析,定位执行时间长的 SQL。
-- 查看慢查询日志`
`SET` `GLOBAL` slow_query_log `=` `'ON'`;
`SET` `GLOBAL` long_query_time `=` `1`; `-- 超过1秒的查询记录
- 避免全表扫描 :使用
EXPLAIN分析执行计划,确保查询使用索引。type的值从最优到最差大致排序如下:system→const→eq_ref→ref→range→index→ALL。SQL 性能优化的目标至少要达到range级别, 要求是ref级别, 如果可以是consts最好。优化手段主要是索引,详见后面"索引优化"章节。
| type | 含义说明 | 常见场景 | 优化方法 | 性能等级 |
|---|---|---|---|---|
| system | 表中只有一行数据(系统表),是 const 的特例 |
空表或单行配置表 | 无需优化,性能最优 | ⭐⭐⭐⭐⭐ |
| const | 通过主键或唯一索引等值查询,最多返回一行 | 1、WHERE id = 1(主键) 2、WHERE email = 'abc@163.com'(UNIQUE 索引) | 确保查询字段有主键或唯一索引 | ⭐⭐⭐⭐⭐ |
| eq_ref | 多表 JOIN 时,使用主键或唯一索引进行等值连接 | JOIN 关联主键或唯一键字段 | 确保关联字段是主键或唯一索引,避免 NULL 值 | ⭐⭐⭐⭐⭐ |
| ref | 使用非唯一索引进行等值查询或 JOIN | 1、WHERE age = 25(age 有普通索引) 2、JOIN使用非唯一外键 | 创建合适的非唯一索引,避免类型转换 | ⭐⭐⭐⭐ |
| range | 使用索引进行范围查询(>、<、BETWEEN、IN 等) | 1、 WHERE id BETWEEN 10 AND 20 2、WHERE status IN (1,2) | 尽量缩小范围;对高频范围字段建索引;避免对索引字段使用函数 | ⭐⭐⭐⭐ |
| index | 全索引扫描 ,遍历整个二级索引树 | 1、SELECT indexed_col FROM table(覆盖索引) 2、无 WHERE 条件但查询字段在索引中 | 建议优化查询条件,改为使用 ref 或 range;避免 SELECT * |
⭐⭐⭐ |
| ALL | 全表扫描 ,遍历整张表 | 索引使用失败的场景,比如: 1、WHERE name LIKE '%Tom'(左模糊) 2、WHERE YEAR(create_time)=2023(函数) 3、无索引字段查询 | 必须优化 : 1、为查询字段添加索引; 2、避免索引失效(如函数、隐式类型转换、左模糊) 3、使用覆盖索引减少回表 | ⭐ |
-
避免
SELECT *:仅选择需要的字段,减少不必要的数据传输。 -
分页优化 :深分页时使用
WHERE id > 上一页最大ID替代LIMIT offset, size。
-- 低效(offset=100万时性能差)`
`SELECT` `*` `FROM` logs LIMIT `1000000`, `20`;
`-- 高效(记录上一页最后一条的ID)`
`SELECT` `*` `FROM` logs `WHERE` id `>` `1000000` LIMIT `20`;`
-
批量操作:批量插入/更新数据,减少网络往返次数。
-
分批读取:获取大量数据时,建议分批次获取数据,减少单次请求的数据量,每次获取数据少于2000条,结果集应小于 1 M。
-
禁止使用 order by rand():order by rand() 会为表增加一个伪列,然后用 rand() 函数为每一行数据计算出 rand() 值,基于该行排序,这通常都会生成磁盘上的临时表,因此效率非常低且无法利用索引。
-
使用连接(JOIN)代替子查询:小表驱动大表,确保关联字段有索引。因为子查询(尤其是相关子查询)可能导致重复执行、难以利用索引、优化器可能选择低效执行计划,而改写为 JOIN 后可更好地利用索引、支持高效连接算法,且执行计划更优、性能更稳定。
-
多表关联查询时,一定要保证被关联的字段需要有索引。
-
尽量避免超过三个表的 JOIN 操作:多表 JOIN 会显著增加查询复杂度、锁竞争和优化器选择执行计划的难度,容易导致性能急剧下降,且难以维护,应通过应用层拆分或冗余设计来避免。
-
尽管避免使用外键与级联:一切外键概念都应该在应用层解决。以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新, 即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群 ;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
-
使用覆盖索引查询:即索引包含查询所需字段,可以避免回表查询。
-
拆分复杂的大SQL为多个小SQL:
| 问题 | 大SQL 的缺点 | 拆分为小SQL 的优势 |
|---|---|---|
| 锁竞争 | 持有锁时间长,阻塞其他操作 | 锁粒度小、时间短,减少阻塞 |
| 执行计划复杂 | 优化器难选择最优路径,易走错索引 | 每个小SQL简单,执行计划更稳定 |
| 内存与资源消耗 | 临时表、排序、join 可能占用大量内存 | 资源消耗分散,降低单次压力 |
| 可读性与维护性 | 难以理解、调试和修改 | 逻辑清晰,易于测试和复用 |
| 缓存友好性 | 结果无法缓存或缓存命中率低 | 小结果可被 Redis/本地缓存复用 |
| 容错与降级 | 一个失败全失败 | 部分失败可降级处理 |
| 扩展性 | 难以并行或异步处理 | 可异步、并发、分页加载 |
-
尽量不在数据库做运算,复杂运算需移到业务应用里完成。
-
拒绝大 sql 语句、拒绝大事务、拒绝大批量,可转化到业务端完成。因为大批量操作可能会造成严重的主从延迟,binlog 日志为 row 格式会产生大量的日志。
-
尽量避免使用存储过程、触发器、函数等,容易造成业务逻辑与 DB 耦合,且影响数据库服务性能。
-
优先使用
UNION ALL而不是UNION,除非你明确需要去重。UNION ALL 直接合并结果集,会保留所有行,包括重复行;UNION 则还需要做去重操作,去重涉及到排序或哈希去重,因此内存、CPU 开销大。
索引使用优化
(详见:MySQL 索引:使用篇)
在 MySQL 中,索引对于提高查询效率至关重要。但并不是所有的场景都适合建立索引,因为索引也会占用额外的存储空间并可能减慢写入操作的速度。合理的使用索引可以显著提升数据库的性能,而不当的使用则可能导致性能下降。
创建索引的场景
一般需要创建索引的场景:
-
在作为主键的列上创建主键索引,强制该列的唯一性和组织表中数据的排列结构。
-
在需要唯一性约束的列上创建唯一索引,可以保证数据的完整性。
-
在经常需要作为查询条件的列(例如 WHERE 子句)上创建索引,可以加快搜索的速度。
-
在经常用在
JOIN连接的列上创建索引,这些列主要是一些外键,可以加快连接的速度。 -
在经常需要根据范围(<,<=,=,>,>=,BETWEEN,IN,不以通配符开始的 LIKE )进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的。
-
在经常需要排序(ORDER BY)和分组(GROUP BY)的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
-
根据业务场景使用组合索引:当一个查询同时需要多个列时,考虑创建组合索引,但需要注意组合索引的最左匹配原则。如果一个索引包含了当前查询所需的所有列,那么就可以直接从索引中获取数据而不需要访问实际的表,这种索引被称为覆盖索引。利用覆盖索引也可以显著提高查询性能。
需要谨慎创建索引的场景:
-
对于含有大量重复值的列,索引的效果不明显,甚至可能降低查询性能。
-
对于非常小的表(如几百条记录以内),全表扫描通常比使用索引更快,因为索引也需要占用存储空间,并且维护索引需要额外的开销。
-
经常进行大量更新操作的列,要谨慎创建索引,因为索引会增加更新操作的时间,因为每次更新都需要同步更新索引。
-
对于那些在查询中很少使用或者参考的列不应该创建索引,因为对闲置索引的维护也需要耗费额外的开销。
-
对于那些定义为 TEXT, IMAGE 和 BIT 数据类型的列不应该创建普通索引,因为这些列的数据量要么相当大,要么取值很少。
索引的设计
-
索引字段尽量使用数字型(简单的数据类型):若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。因为存储引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
-
尽量不要让字段的默认值为
NULL:含有空值的列很难进行查询优化,因为NULL值在索引结构中的处理方式与非NULL值不同,它们使得索引存储、索引的统计信息以及比较运算等更加复杂,可能会导致额外的扫描操作。 -
能使用唯一索引就要使用唯一索引,提高查询效率。
-
优先选择高选择性的列(选择性 = 不重复值 / 总行数)。选择性越高,索引效率越高,例如用户邮箱、手机等高选择性列是索引的理想候选,避免在性别、状态(0/1)等低选择性列上单独建索引。
-
前缀索引:
-
在
varchar字段上建立索引时,应指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90% 以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。 -
对字符串进行索引,如果可能应该指定一个前缀长度。前缀索引是一种能使索引更小、更快的有效办法。要选择足够长的前缀以保证较高的选择性,同时又不能太长(以便节约空间)。同时要注意, MySQL 无法使用前缀索引做
order by和group by,也无法使用前缀索引做覆盖扫描。 -
对于 BLOB 、TEXT 或者很长的 VARCHAR 类型的列,必须使用前缀索引,因为 MySQL 不允许索引这些列的完整长度。
-
-
如果对大的文本进行搜索,使用全文索引而不要使用
LIKE '%...%'。不过全文搜索其实也不是 MySQL 擅长的,更好的应该是使用专业的搜索引擎来检索大文本。 -
使用组合索引代替多个单列索引,这样一次索引查找便可高效支持多列组合的条件与范围查询。当使用多个单列索引时,MySQL可能需要执行索引合并(Index Merge),将来自不同索引的结果集合并,性能比一次组合索引查询要差。
-
使用组合索引时,应将选择性最高的列放在前面,以最大化索引的过滤能力。
-
定期检查重复/冗余的索引、不使用的索引:MySQL 允许在相同的列上创建多个索引,无论是有意还是无意的。大多数情况下不需要使用冗余索引,每个索引都会增加写操作的开销(INSERT / UPDATE / DELETE)。可以定期使用
SHOW INDEX FROM table_name和EXPLAIN分析索引使用情况,删除未使用或冗余的索引。 -
随着应用的发展,数据库的使用模式可能会发生变化,因此也有必要定期检查和调整索引策略。
正确使用索引的姿势
-
分析 SQL 语句执行计划:在执行关键查询前,使用
EXPLAIN查看是否使用了预期的索引。关注type(最好为const/ref,避免ALL全表扫描)、key(实际使用的索引)、rows(扫描行数)等字段。 -
合理使用
IN和OR:-
IN通常可以使用索引(尤其是小范围)。 -
多个
OR条件可能导致索引合并(Index Merge),但效率不一定高,建议用UNION优化或重构查询。
-
-
尽量避免使用
!=、<>或NOT IN,这些反向查询操作通常会导致引擎放弃使用索引而进行全表扫描。 -
使用组合索引查询需要遵守"最左匹配原则",否则会导致组合索引失效。最左匹配原则要求查询必须从索引的最左边的列开始,且不能跳过中间某一索引列。
`KEY a_b_c(a, b, c)
`-- 符合最左匹配原则:`
`WHERE` a`=`? `and` b`=`? `and` c`=`?
`WHERE` a`=`? `and` b`=`?
`WHERE` a`=`?
`-- 不符合最左匹配原则`
`WHERE` b`=`? `and` c`=`? `-- 未从a索引开始`
`WHERE` b`=`? `-- 未从a索引开始`
`WHERE` c`=`? `-- 未从a索引开始`
`WHERE` a`=`? `and` c`=`? `-- 跳过了b索引
- 使用组合索引排序时,
ORDER BY也要遵守"最左匹配原则":索引的顺序与ORDER BY中的列顺序相同,且所有的列是同一方向(全部升序或者全部降序)。
`KEY a_b_c(a, b, c)
`-- order by 能使用索引最左前缀:`
`ORDERBY` a
`ORDERBY` a,b
`ORDERBY` a,b,c
`ORDERBY` a `DESC`, b `DESC`, c `DESC`
`-- 如果WHERE使用索引的最左前缀定义为常量,则order by能使用系引`
`WHERE` a`=`const `ORDERBY` b,c
`WHERE` a`=`const `AND` b`=`const `ORDERBY` c
`WHERE` a`=`const `ORDERBY` b,c
`WHERE` a`=`const `AND` b`>`const `ORDERBY` b,c
`-- 不能使用索引进行排序`
`ORDERBY` a `ASC`, b `DESC`,C `DESC-- 排序不一致`
`ORDERBY` b,c `-- 丢失a索引`
`WHERE` a`=`const `ORDER` c `-- 丢失b系引`
`WHERE` a`=`const `ORDERBY` a,d `-- d不是素引的一部分
- 尽量避免在索引列上进行函数操作,否则会导致索引失效。
SELECT` `*` `FROM` users `WHERE` `YEAR`(create_time) `=` `2023`; `-- 索引失效`
`-- 应改为:`
`SELECT` `*` `FROM` users `WHERE` create_time `>=` `'2023-01-01'` `AND` create_time `<` `'2024-01-01'`;`
- 尽量避免在索引列上进行计算或表达式操作,否则会导致索引失效。
SELECT` `*` `FROM` users `WHERE` age `+` `10` `=` `30`; `-- 索引失效`
`-- 应改为:`
`SELECT` `*` `FROM` users `WHERE` age `=` `20`;`
- 防止因字段类型不同造成的隐式转换, 导致索引失效。
-- 如何 id 类型是字符串,SQL语句中使用数字,会导致索引失效`
`SELECT` `*` `FROM` users `WHERE` id `=` `123`;`
- 尽量避免以通配符开始的
LIKE模糊查询。如果确实需要大量左模糊或者全模糊查询,建议走搜索引擎来解决。索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
SELECT` `*` `FROM` users `WHERE` name `LIKE` `'张三%'`; `-- 可以使用索引`
`SELECT` `*` `FROM` users `WHERE` name `LIKE` `'%张三'`; `-- 索引失效
OR条件:用OR分割开的条件, 如果OR前的条件中的列有索引,而后面的列中没有索引, 那么涉及到的索引都不会被用到。可以用UNION ALL代替相同效果:
-- 假设 num1 有索引,num2 没有索引`
`SELECT` `*` `FROM` t `WHERE` num1`=10` `OR` num2`=20`; `-- num1索引可能失效`
`-- 可改为:`
`SELECT` `*` `FROM` t `WHERE` num1`=10`
`UNION` `ALL`
`SELECT` `*` `FROM` t `WHERE` num2`=20`; `-- num1索引生效
锁使用优化
(详见:MySQL 锁机制详解)
优化 MySQL 中的锁性能对于提高数据库的整体性能至关重要,尤其是在高并发环境中。
-
使用合适的存储引擎:相比 MyISAM 的表级锁定机制,InnoDB 提供了行级锁定以及多版本并发控制(MVCC),这使得它在处理大量读写操作时表现更佳。因此,在大多数情况下推荐使用 InnoDB。
-
选择合适的事务隔离级别 :不同的隔离级别对应不同的锁策略,选择合适的隔离级别可以在一致性和并发性之间取得平衡。例如,使用较低的隔离级别如
READ COMMITTED可以减少锁的持有时间和范围,但可能会牺牲一些数据一致性保证。 -
尽量使用索引:确保查询条件中使用的列上有适当的索引,这样可以减少锁定的数据量,因为 InnoDB 只会在满足条件的行上加锁而不是整个表。应避免全表扫描,全表扫描可能导致大量的行被锁定,增加死锁的可能性。
-
缩短事务长度:尽量减少事务的持续时间可以降低锁冲突的概率。确保只在必要的时候才开始事务,并尽快提交或回滚。
-
批量操作事务:将多个相关的小操作事务合并成一个较大的操作事务执行,以减少获取锁的次数。
-
一次性足够级别的获取锁:给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁。但是不要申请超过实际需要的锁级别。
-
统一操作顺序:不同的程序访问同一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行,这样可以大大减少死锁的概率。
-
应用层优化:通过重新设计应用程序逻辑来减少同时对同一资源的锁竞争。比如,调整业务流程以分散对热点数据的访问。
-
配置参数调整:
-
innodb_lock_wait_timeout:设置合理的超时值,防止长时间等待锁导致的阻塞问题。 -
innodb_print_all_deadlocks:启用此选项可以帮助监控并分析生产环境中的所有死锁情况。
-
-
命令行诊断 :可以定期使用
SHOW STATUS来查看当前的锁状态、锁争用情况等。
MySQL Server优化
-
连接数与线程优化 :调整
max_connections,控制 MySQL 服务器允许同时建立的最大客户端连接数,防止资源耗尽。调整thread_cache_size,控制可复用的空闲线程缓存数量,减少频繁创建和销毁线程的开销。 -
连接超时配置优化 :调整
wait_timeout(用于非交互式连接,如应用连接池、脚本)/interactive_timeout(用于交互式连接,如 MySQL 客户端命令行),在连接空闲(无任何查询)超过设定时间后,主动释放长时间空闲的连接,避免连接数耗尽。推荐设置为 600(10分钟)或 1800(30分钟)。 -
InnoDB 存储引擎配置优化:
| 类别 | 配置项 | 推荐值(参考) | 说明 |
|---|---|---|---|
| 内存管理 | innodb_buffer_pool_size 数据和索引缓冲大小 | 70%~80% 物理内存 | 缓存数据页和索引页的内存区域,是最关键的性能参数。 |
| 事务日志 | innodb_log_file_size Redo Log 大小 | 1~2G(多个文件) | Redo Log 文件大小,影响写性能和崩溃恢复时间。 |
| innodb_log_buffer_size Redo Log 写入缓冲大小 | 64M~256M | ||
| 刷盘策略 | innodb_flush_log_at_trx_commit 事务日志刷盘频率 | 1(每次提交都刷盘,最安全)或 2(写入 OS 缓存,每秒刷盘,可以平衡安全与性能) | 事务持久性控制,控制事务提交时 Redo Log 的刷盘策略,直接影响数据安全与性能。 |
| IO 并发 | innodb_io_capacity / innodb_io_capacity_max 磁盘 IO 能力提示 | 普通 SSD:2000 / 4000 | 告诉 InnoDB 磁盘的 IO 能力,用于控制后台刷脏速度,避免 Checkpoint 落后太多导致"写放大"或 IOPS 瓶颈。 |
| 并发控制 | innodb_thread_concurrency 线程并发限制 | 0(表示不限制,由 InnoDB 自动管理)或 CPU 核数的 1~2 倍 | 限制并发线程数,防止线程争抢导致上下文切换开销。 |
| innodb_read_io_threads /write_threads IO 线程数 | 4~8(高并发可调大) | ||
| 死锁与锁 | innodb_deadlock_detect 死锁检测开关 | ON(默认) | 死锁自动检测。 |
| innodb_lock_wait_timeout 锁等待超时时间 | 50~120 秒 | ||
| 其他关键项 | innodb_flush_method 文件系统刷盘方式 | O_DIRECT(Linux 设置为 O_DIRECT,可以绕过 OS 缓存,避免双重缓存和脏页冲突) | 控制数据文件和日志文件的刷盘方式。 |
| sync_binlog MySQL Server 层的 Binlog 刷盘频率 | 1(每次事务提交都刷盘,最安全,但性能低)或 1000(每 1000 次提交刷一次,性能高,但可能丢日志) | 控制 MySQL Server 层 Binlog 的同步频率,主要用于数据恢复、主从复制等场景。 |
-
硬件优化:
-
使用 SSD 替代 HDD,提升 I/O 性能。
-
增加内存以扩大缓冲池,减少磁盘访问。
-
MySQL Server 调优原则:
-
先监控,再优化 :使用
SHOW ENGINE INNODB STATUS、performance_schema、慢查询日志等分析瓶颈。 -
按场景权衡:安全性 vs 性能、OLTP vs OLAP。
-
逐步调整:每次只改一个参数,观察效果。
-
备份与测试:生产变更前在测试环境验证。
MySQL 架构性能优化
-
主从复制与读写分离:主库处理写操作,从库分担读压力。可以使用中间件(如 MyCat、ShardingSphere)实现自动路由。
-
分库分表:
-
分表:
-
垂直拆分:避免单表单行太大,引起分页存储。可以将一个包含了很多字段的大表拆分为多个小表,每个表包含部分字段。
-
水平拆分:解决单表容量不足问题,把一张大表拆分成多个多张小表,每张小表里仅包含原表的部分行数据。建议单表超过 500w 行,或单表容量超过 2GB,才需要水平分表。
-
-
分库:解决服务器性能问题,多库可以使得并发处理能力更强。
-
应用层优化
-
缓存策略:使用 Redis 等缓存高频查询结果,减少数据库压力。
-
连接池管理 :使用 HikariCP 或 Druid,控制连接池大小(建议
CPU核心数 * 2 + 1)。 -
连接超时时间管理 :应用层连接超时时间的合理控制是保障系统稳定性、防止数据库资源耗尽的关键措施。应根据业务场景设置合适的超时阈值,避免长查询或网络问题导致连接堆积甚至耗尽而拒绝服务。如果应用层未设置超时,查询卡住时连接会一直占用,最终导致数据库连接数打满(
max_connections达到上限),引发雪崩。
| 超时类型 | 说明 | 建议值(参考) |
|---|---|---|
| connectTimeout | 建立 TCP 连接的超时时间 | 5 ~ 10 秒 |
| socketTimeout / readTimeout | 读取数据(查询执行)的超时时间 | 1 ~ 30 秒(按业务) |
| connectionLifetime | 连接最大存活时间(防长连接老化) | 30 ~ 60 分钟 |
| wait_timeout (数据库端配合) | 连接空闲多久后被服务端关闭 | 建议设为 600 ~ 1800 秒 |
`jdbc:mysql:`//`host:`3306/`dbname?
connectTimeout`=10000` `&` `//` `10`秒
socketTimeout`=30000` `&` `//` `30`秒
autoReconnect`=false` `&` `//` 不推荐自动重连
maxLifetime`=1800000` `//` `30`分钟(连接池控制)`