MySQL高并发时缓存易击穿雪崩,需通过业务维度key隔离、避免SELECT...FOR UPDATE、用READ COMMITTED隔离级、TTL加随机偏移、连接池与缓存更新时机同步、禁用已废弃Query Cache、合理配置innodb_buffer_pool_size及SQL层兜底(如id>0)来优化。
当 SELECT 请求并发突增(比如秒杀、榜单刷新),即使加了 Redis 缓存,仍可能因缓存未命中集中打到 MySQL,引发连接数飙升、Waiting for table metadata lock 或 Lock wait timeout exceeded。这不是缓存没用,而是缓存策略和 MySQL 并发控制没对齐。
"user:profile:" ),避免全量缓存失效导致穿透SELECT ... FOR UPDATE 包裹纯查询逻辑——它会升级为行锁甚至间隙锁,阻塞其他并发 SELECTREAD COMMITTED 隔离级别,而非默认的 REPEATABLE READ,减少 MVCC 版本链长度和间隙锁范围300 + random(60) 秒),防止批量失效应用层用连接池(如 HikariCP、mysql-connector-python 的 pool_size)时,缓存更新若发生在事务提交前,会导致其他连接查到脏数据;若在事务外异步更新,又可能因事务回滚造成缓存与 DB 不一致。
@Transactional + @CacheEvict,确保事务成功才触发删除)SET 带大 value 或 pipeline),否则拖慢事务,抬高锁持有时间max_pool_size)需略大于缓存失效时的并发重建请求数,否则重建线程会排队等连接,放大延迟MySQL 8.0 已彻底移除 query_cache_ty 和相关变量。即使你用的是 5.7,开启 
query_cache_size > 0 也会在高并发下成为瓶颈:每次写入表都会清空该表所有缓存结果,且缓存锁是全局互斥锁,SELECT 多了反而卡住。
query_cache_type = 0,关闭它,把资源留给 InnoDB buffer poolinnodb_buffer_pool_size 应设为物理内存的 50%–75%,比任何 Query Cache 都更直接提升并发读性能恶意或异常请求查大量不存在的 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 的查询——这是穿透典型特征SELECT u.* FROM user u WHERE u.id = ? AND u.id > 0 AND u.status = 'active' LIMIT 1;
真正难的不是配缓存,是判断哪条 SQL 在并发下会抢锁、哪次缓存失效会连环触发重建、以及 MySQL 的 buffer pool 和连接池怎么跟你的缓存 TTL 数值咬合。这些细节不调参、不看慢日志、不模拟压测,只靠“加 Redis”解决不了问题。