mysql并发与缓存如何配合使用_mysql性能架构说明

12次阅读

MySQL高并发时缓存易击穿雪崩,需通过业务维度key隔离、避免SELECT…FOR UPDATE、用READ COMMITTED隔离级、TTL加随机偏移、连接池与缓存更新时机同步、禁用已废弃Query Cache、合理配置innodb_buffer_pool_size及SQL层兜底(如id>0)来优化。

mysql并发与缓存如何配合使用_mysql性能架构说明

mysql 并发高时缓存容易击穿或雪崩

select 请求并发突增(比如秒杀、榜单刷新),即使加了 redis 缓存,仍可能因缓存未命中集中打到 MySQL,引发连接数飙升、Waiting for table metadata lockLock wait timeout exceeded。这不是缓存没用,而是缓存策略和 MySQL 并发控制没对齐。

  • 缓存 key 设计必须包含业务维度隔离(如 "user:profile:"),避免全量缓存失效导致穿透
  • 读多写少场景下,禁止用 SELECT ... FOR UPDATE 包裹纯查询逻辑——它会升级为行锁甚至间隙锁,阻塞其他并发 SELECT
  • 高并发读建议用 READ COMMITTED 隔离级别,而非默认的 REPEATABLE READ,减少 MVCC 版本链长度和间隙锁范围
  • 缓存过期时间(TTL)别设固定值,应加随机偏移(如 300 + random(60) 秒),防止批量失效

MySQL 连接池与缓存更新时机必须同步

应用层用连接池(如 HikariCP、mysql-connector-pythonpool_size)时,缓存更新若发生在事务提交前,会导致其他连接查到脏数据;若在事务外异步更新,又可能因事务回滚造成缓存与 DB 不一致。

  • 强一致性要求:缓存更新放在事务提交后(如 spring@Transactional + @CacheEvict,确保事务成功才触发删除)
  • 最终一致性可接受:用 MySQL binlog 解析(如 Canal、Debezium)监听变更,解耦缓存更新,避免应用层事务复杂度
  • 禁止在事务中执行耗时缓存操作(如 redis SET 带大 value 或 pipeline),否则拖慢事务,抬高锁持有时间
  • 连接池最大连接数(max_pool_size)需略大于缓存失效时的并发重建请求数,否则重建线程会排队等连接,放大延迟

Query Cache 已废弃,别再依赖它做并发优化

MySQL 8.0 已彻底移除 query_cache_type 和相关变量。即使你用的是 5.7,开启 query_cache_size > 0 也会在高并发下成为瓶颈:每次写入表都会清空该表所有缓存结果,且缓存锁是全局互斥锁,SELECT 多了反而卡住。

  • 替代方案是应用层显式缓存(Redis/memcached)+ 主动失效,粒度可控
  • 如果仍用 MySQL 5.7 且无法改架构,至少把 query_cache_type = 0,关闭它,把资源留给 InnoDB buffer pool
  • innodb_buffer_pool_size 应设为物理内存的 50%–75%,比任何 Query Cache 都更直接提升并发读性能

缓存穿透时 MySQL 的防护要落在 SQL 层

恶意或异常请求查大量不存在的 id(如 SELECT * FROM user WHERE id = -12345),缓存层没命中,直接压到 MySQL。这时光靠缓存布隆过滤器不够,MySQL 本身也得有兜底。

  • 在关键查询上加 WHERE id > 0 AND id 类型的硬约束,避免全表扫描无效值
  • 对高频查询字段(如 user_id)建唯一索引,让 SELECT ... LIMIT 1 能走索引快速返回空结果,而不是等扫描完才确认无数据
  • pt-query-digest 定期分析慢日志,重点关注 Rows_examined 高但 Rows_sent 为 0 的查询——这是穿透典型特征
  • 应用层对非法参数(如负 ID、超长字符串)做前置校验,不放行到 DAO 层,比在 MySQL 拦截更省资源
SELECT u.*  FROM user u  WHERE u.id = ?    AND u.id > 0    AND u.status = 'active' LIMIT 1;

真正难的不是配缓存,是判断哪条 SQL 在并发下会抢锁、哪次缓存失效会连环触发重建、以及 MySQL 的 buffer pool 和连接池怎么跟你的缓存 TTL 数值咬合。这些细节不调参、不看慢日志、不模拟压测,只靠“加 Redis”解决不了问题。

text=ZqhQzanResources