现场是这样的。8 核 16G 的 MariaDB 10.5 压到两千并发,CPU 使用率只有四成多,可 vmstat 里 cs 每秒三十万次,接口延迟翻了一倍,cpu 那一列的时间大半花在系统态。

中间走过弯路,把「连接频繁建立断开,新线程创建销毁把开销再抬高一层」当成主因,改完现象没变。

真正麻烦的地方在于,几个原因的现象几乎一样。每个连接对应一个线程,连接数上千之后调度开销超过真正的计算;线程之间抢同一把锁,唤醒和挂起的次数随并发线性增长;线程数远超核数,缓存局部性变差,每次切换都要重新加载上下文。

上来先确认切换次数与系统态占比

vmstat 1 3

接着看线程数相对并发是什么量级

mysql -e 'show global status like "Threads_connected"; show global status like "Threads_running";'

再往下改用线程池模式并重启

sed -i '/^\[mysqld\]/a thread_handling=pool-of-threads' /etc/my.cnf && systemctl restart mariadb

复压一次看切换次数是否下降

vmstat 1 3 | tail -1

怎么算真的好了,看的是同一批现象。同样两千并发下 cs 降到每秒几万次,系统态占比明显下降,接口 p99 回到压测前的水平,慢查询数量同步减少。

补一句。线程池对短查询收益明显,长事务多的库开线程池要慎重,容易把连接饿死在池里。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189