Mysql的binlog和redolog和undolog
Mysql如何设计索引系统?
一些“临时”的数据库优化方法
业务高峰期,临时需要优化去将业务数据量跑起来,至于那些常规的方法,我们应该已经优化过了,那么有那些方法,是临时就可以优化的呢?
问题:由于大量的请求打击到db,db上的连接数超过了max_connections参数,这个参数是用来保护mysql连接数上限的,超过这个值,系统就会拒绝接下来的连接请求,并反应“Too many connections”,对于被拒绝的连接请求来说,从业务角度看就是数据库不可用。
虚假解决一:多余该问题,我们可以将其设置高,也许能解决问题,但是同时更多的连接会有更多的权限校验等逻辑,也需要消耗系统资源,可能使得结果适得其反。
可考虑思路一:先处理掉那些站着连接但是不工作的线程。
max_connection的计算,并不是当前有多少连接正在运行查数据,而是实打实的有多少连接,不管他有没有工作,都占用一个连接数,对于这些不需要工作的连接,可以使用kill connection主动踢掉。这个行为和事先设置wait_timeout效果是一样的,对于超过多久没运动的连接,就断开,就不占用坑位。但直接kill掉,可能也是有损失的。
在 show processlist 的结果里,踢掉显示为 sleep 的线程,可能是有损的。我们来看下面这个例子。
在上面这个例子里,如果断开 session A 的连接,因为这时候 session A 还没有提交,所以 MySQL 只能按照回滚事务来处理;而断开 session B 的连接,就没什么大影响。所以,如果按照优先级来说,你应该优先断开像 session B 这样的事务外空闲的连接。【对于没结束但是空闲的连接,还是不要处理人家好】,但有时候一些事务线程会持续很久很久,久到你认为它sleep了,可以看
session C 在 T 时刻之后的 30 秒执行 show processlist,看到的结果是这样的。
可以看到平平无奇的线程4和5,但是查一查事务情况表,查information_schema 库的 innodb_trx 表。
显示线程4的事务正在running,说明他只是跑事务跑到外界看起来是sleep了,因此kill掉线程4是不可以的,因此缎断掉那些没有正在进行东西的线程,是不错的选择。但是最好也通知一下开发团队,因为这些连接的请求会返回
“ERROR 2013 (HY000): Lost connection to MySQL server during query”。
可考虑思路二:减少连接过程的消耗。
连接过程中,存在一些权限校验,我们可以通过–skip-grant-tables重启数据库,这样会跳过权限校验,自己玩mysql的时候也可以通过这条命令重置密码啥的,反正就可以玩玩权限,但是风险很高
普通的慢查询性能问题
1、索引没设计好
2、sql语句没写好(没优化到最佳如union和or,索引失效)
3、没走索引
比如,通过下面这个过程,我们就可以预先发现问题。上线前,在测试环境,把慢查询日志(slow log)打开,并且把 long_query_time 设置成 0,确保每个语句都会被记录入慢查询日志;在测试表里插入模拟线上的数据,做一遍回归测试;观察慢查询日志里每类语句的输出,特别留意 Rows_examined 字段是否与预期一致。
某个语句qps暴增
暴增导致mysql服务功能异常,出于全局决策考虑,可以先阻止该语句,
- 一种是由全新业务的 bug 导致的。假设你的 DB 运维是比较规范的,也就是说白名单是一个个加的。这种情况下,如果你能够确定业务方会下掉这个功能,只是时间上没那么快,那么就可以从数据库端直接把白名单去掉。
- 如果这个新功能使用的是单独的数据库用户,可以用管理员账号把这个用户删掉,然后断开现有连接。这样,这个新功能的连接不成功,由它引发的 QPS 就会变成 0。
- 如果这个新增的功能跟主体功能是部署在一起的,那么我们只能通过处理语句来限制。这时,我们可以使用上面提到的查询重写功能,把压力最大的 SQL 语句直接重写成”select 1”返回。
操作3是一个比较风险的操作,可能导致1、彼得功能也有这个sql语句,那么可能会造成别的功能也返回1,显然不行,2、许多业务并不是只有一个语句去完成业务,因此这里结果更改,可能会波及到更多的业务错误。因此操作1和操作2,会是解决问题的更优解,但是这些更优解,需要更多的系统准备和处理措施,这也反应出一个道理:一个系统准备和防范的措施越规范越多,其往往就具有更好的稳定性。
