现场是这样的。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 回到压测前的水平,慢查询数量同步减少。
补一句。线程池对短查询收益明显,长事务多的库开线程池要慎重,容易把连接饿死在池里。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
