22 | MySQL有哪些“饮鸩止渴”提高性能的方法?

一、短连接风暴

短连接:执行很少的 SQL 语句就断开,需要再连。高峰期可能连接数暴涨

成本高。除三次握手,需登录权限读写权限

max_connections控制连接数,超过报“Too many connections”。

调高max_connections 有风险。改太大,让更多的连接都可以进来,系统负载大,大量的资源耗费在权限验证等逻辑上,已经连线程拿不到 CPU 资源去执行业务的 SQL 请求。解决方法:

2.1方法1:处理占连接不工作线程

max_connections 计算,不看谁running占计数位 kill connection 主动踢掉。跟事先设置 wait_timeout 效果一样:空闲 wait_timeout 多少秒之后,断开连接。show processlist 踢掉sleep 线程,可能有损

图 1 sleep 线程的两种状态

A 没有提交,回滚; B 没影响。哪些事务外空闲? C 在 T 时刻之后30 秒执行 show processlist

图 2 sleep 线程的两种状态  

id=4 和 id=5 都是 Sleep。看事务具体状态: information_schema库的 innodb_trx 表。

图 3 从 information_schema.innodb_trx 查询事务状态

trx_mysql_thread_id=4, id=4 事务中

kill connection + id 的命令, sleep主动断开,客户端不会马上知道。发起请求报错“ERROR 2013 (HY000): Lost connection to MySQL server during query”。

可能有损,不重连直接用已经不能用句柄重试。从应用端看上“MySQL没恢复”。断开连接要通知到业务开发。

1.2 方法2:减少连接过程消耗

短时间大量申请连接备用,跳过权限验证:–skip-grant-tables重启数据库

“饮鸩止渴”,风险极高,不建议用(尤其库外网可访问)

默认--skip-networking 参数打开,只被本地客户端连接。

查询、更新导致性能问题:慢查询导致, QPS突增导致

二、慢查询性能问题

引发慢查询可能&解决方案:索引没设计好、SQL 没写好、选错索引

2.1索引没设计好

通过紧急创建索解决。高峰期被语句打挂,直接执行 alter table。主库 A、备库 B:

1.  在备库 B 上执行 set sql_log_bin=off,不写 binlog,执行 alter table 加索引;

2.  主备切换

3.  A 上执行 set sql_log_bin=off,执行 alter table 加索引。

“古老” DDL 方案。平时变更, gh-ost 更稳妥。紧急这个效率高

2.2语句没写好

18 篇文章《为什么这些 SQL 语句逻辑相同,性能却差异巨大?》错误导致没用上索引。

query_rewrite 把输入语句改成另一模式:

被错误地写成了 select * from t where id + 1 = 10000增加改写规则

mysql> insert  into query_rewrite.rewrite_rules(pattern, replacement, pattern_database)  values ("select * from t where id + 1 = ?", "select * from t  where id = ? - 1", "db1");

call  query_rewrite.flush_rewrite_rules();  这个存储过程,让插入新规则生效,“查询重写”。确认:

图 4 查询重写效果

2.3选错索引

10 篇文章MySQL 为什么有时候会选错索引?》查询重写功能,原语句加 force index解决

前两种实际上出现最多。预先发现问题(上线前的“额外”时间,会省下故障复盘时间):

1.  慢查询日志(slow log)打开,long_query_time = 0,确保每个语句都被记录

2.  模拟线上数据,回归测试

3. 观察慢每类语句,Rows_examined是否与预期一致

新增SQL不多,手动跑。修改表结构,全量回归测。开源工具pt-query-digest(https://www.percona.com/doc/percona-toolkit/3.0/pt-query-digest.html)。

三、QPS 突增问题

突然高峰,或者bug, QPS 暴涨,MySQL 压力大,影响服务。下功能,数据库端处理:

1.  白名单去掉:新bug 导致。DB 运维规范(白名单一个个加)。确定下功能,时间上没那么快。

2. 断开连接: 新功能单独库,删掉用户。新功能连接不成功,引发 QPS  0。

3.  处理语句(优先级低)新功能跟主体部署一起,查询重写功能,压力最大 SQL 语句写成"select 1"返回。副作用:

1.  别的也用误伤

2.  很多业务不是靠这一个完成, select 1 导致后面失败

1 和 2 依赖于规范运维:虚拟化、白名单机制、业务账号分离

小结

粗暴地拒绝、断开连接重写语句绕坑

避免大量用短连接。连接异常断开常有,代码要有重连并重试机制。

DBA 通过语句重写处理,风险高,做好 SQL 审计可减少

解决方法主要在 server 层

思考:业务高峰期临时救火场景?怎么处理?

评论1

delete大事务导致磁盘满,数据库hang住,连接不上,无法kill掉大事务.现象是:

binlog一个文件50G(说明事务已经执行完成,fsync相当copy,空间占满)

lsof | grep delete 该tmp文件100多G(binlog_cache不够用,binlog写进tmp,binlog完全落盘删除之前tmp)

redo log还是只有4个组,每个文件1G(循环写,redo log分为mtx落地到磁盘上没有一次性暴增,还是原大小持续写.)

undo log大概有100来G


解决办法:切从库,kill主库进程。binlog缩小为原来。主库启recovery非常慢。后面kill掉,innodb_force_recovery=3(不执行事务回滚操作)恢复,recovery半天没反应。不是重要库,新主库备份文件重做了之前的主库,从库启。

后续测试:还耗时,redo log一直变,binlog没变,recovery=3

Binlog 大是大事务崩溃恢复处理redolog 多,耗时在这(通过redo log恢复数据页。)

最老binlog移动到别的盘(确定备份就删)。强制重启伤,做好监控,不让磁盘100%写满

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容