MySQL不提供任务级并发限制,需在应用层或中间件控制;可用max_execution_time防长查询;GET_LOCK()可模拟轻量级并发控制;连接池和Proxy层才是真正的并发管控入口。

MySQL 本身不提供任务级并发限制
MySQL 没有内置的「任务队列」或「并发数控制器」,max_connections 控制的是连接数,不是业务任务的并发执行数。你看到的“多个定时任务同时跑满 CPU”或“批量导入压垮从库”,本质是应用层没做节流,MySQL 只负责执行发来的 SQL。
真正能控制并发的地方在应用侧或中间件,MySQL 层最多配合做些轻量级兜底。
用 max_execution_time 防止长查询拖垮实例
这是 MySQL 5.7.8+ 提供的实用机制,对单条 SELECT 设置最大执行时间(毫秒),超时自动 kill,避免慢查询堆积阻塞其他请求。
- 只对
SELECT生效(INSERT/UPDATE/DELETE 不支持) - 需在会话或全局开启:
SET SESSION max_execution_time = 3000 - 对
UNION、子查询、派生表都有效,但不中断正在写的磁盘 IO - 注意:如果客户端重试失败查询,可能引发雪崩,得配合应用层退避逻辑
示例:
SELECT /*+ MAX_EXECUTION_TIME(5000) */ * FROM orders WHERE status = 'pending';
靠应用层信号量 + 表锁模拟并发控制
没有分布式锁服务时,可用 MySQL 自带的 GET_LOCK() 做简单互斥,适合低频、非核心任务(比如每小时一次的报表生成)。
-
GET_LOCK('report_task', 0)返回 1 表示抢到锁,0 表示被占用,NULL 表示超时(第二个参数为等待秒数) - 必须配对调用
RELEASE_LOCK('report_task'),否则锁一直残留 - 锁名是字符串,建议加前缀避免冲突,如
'batch_import_user_v2' - 该锁作用域是 connection 级,连接断开自动释放,但异常中断可能导致锁滞留,需加超时清理逻辑
别用 SELECT ... FOR UPDATE 模拟,它依赖事务和索引,容易死锁且无法跨会话协调。
Proxy 层或连接池才是真正可控的入口
如果你的任务由应用统一发起(比如 Python 的 sqlalchemy 或 Java 的 HikariCP),并发控制应该落在连接池配置上:
- 设
max_pool_size为 10,就天然限制最多 10 个任务并行查库 - 结合
connection_timeout和validation_timeout避免借不到连接时无限等待 - 若用
ProxySQL或MaxScale,可配置 query rule 匹配特定 SQL 模式,再限速或打标路由 - 注意:连接池限制的是「并发连接数」,不是「并发事务数」;一个连接内仍可能串行跑多个事务
真正难控的是那些直连 MySQL 的脚本(mysql -e "source batch.sql")、定时任务或异步 worker——它们绕过所有池化逻辑,最容易成为并发黑洞。


















