热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:MySQL45讲提升性能的临时方案

篇首语:本文由编程笔记#小编为大家整理,主要介绍了MySQL45讲提升性能的临时方案相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了MySQL45讲提升性能的临时方案相关的知识,希望对你有一定的参考价值。






业务高峰期,生产环境的mysql压力太大,没法正常响应,需要短期内临时性地提升一些性能

接下来看看这些临时方案,并着重说说可能存在的风险


一、短连接风暴

正常的短连接模式就是连接到数据库后,执行很少的SQL语句就断开,下次需要的时候再重连
如果使用的是短连接,在业务高峰期的时候,就可能出现连接数突然暴涨的情况


1.1 短连接成本

MySQL建立连接的过程,成本是很高的,除了正常的网络连接三次握手外,还需要做登录权限判断和获得这个连接的数据读写权限

在数据库压力比较小的时候,这些额外的成本并不明显
但是,短连接模型存在一个风险,就是一旦数据库处理得慢一些,连接数就会暴涨


1.2 max_connections

max_connections参数,用来控制一个MySQL实例同时存在的连接数的上限

超过这个值,系统就会拒绝接下来的连接请求,并报错提示Too many connections
对于被拒绝连接的请求来说,从业务角度看就是数据库不可用

在机器负载比较高的时候,处理现有请求的时间变长,每个连接保持的时间也更长,这时,再有新建连接的话,就可能会超过max_connections的限制

碰到这种情况时,一个比较自然的想法,就是调高max_connections的值

但这样做是有风险的,因为设计max_connections这个参数的目的是想保护MySQL,如果把它改得太大,让更多的连接都可以进来,那么系统的负载可能会进一步加大,大量的资源耗费在权限验证等逻辑上,结果可能是适得其反,已经连接的线程拿不到CPU资源去执行业务的SQL请 求

那么这种情况下,还有没有别的建议呢?接下来有两种有损的处理方法


1.3 处理连接但不工作的线程

第一种方法是先处理掉那些占着连接但是不工作的线程

max_connections的计算,不是看谁在running,是只要连着就占用一个计数位置
对于那些不需要保持的连接,可以通过kill connection主动踢掉,这个行为跟事先设置wait_timeout的效果是一样的

设置wait_timeout参数表示的是,一个线程空闲wait_timeout这么多秒之后,就会被MySQL直接断开连接

但是需要注意,在show processlist的结果里,踢掉显示为sleep的线程,可能是有损的

看看下面这个例子
在这里插入图片描述
在上面这个例子里:


  • 如果断开session A的连接,因为这时候session A还没有提交,所以 MySQL只能按照回滚事务来处理
  • 如果断开session B的连接,就没什么大影响

所以,如果按照优先级来说,你应该优先断开像session B这样的事务外空闲的连接

但是,怎么判断哪些是事务外空闲的呢?session C在T时刻之后的30秒执行show processlist的结果如下:
在这里插入图片描述
上图中id=4和id=5的两个会话都是Sleep 状态

要看事务具体状态的话,可以查information_schema库的innodb_trx表

select * from 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.4 减少连接过程的消耗

第二种方法是减少连接过程的消耗

有的业务代码会在短时间内先大量申请数据库连接做备用,如果现在数据库确认是被连接行为打挂了,那么一种可能的做法,是让数据库跳过权限验证阶段

跳过权限验证的方法是:重启数据库,并使用–skip-grant-tables参数启动
这样,整个MySQL会跳过所有的权限验证阶段,包括连接过程和语句执行过程在内

但是,这种方法风险极高,特别不建议使用的方案,尤其数据库外网可访问的话,就更不能这么做了



在MySQL 8.0版本里,如果启用–skip-grant-tables参数,MySQL会默认把 --skip-networking参数打开,表示这时候数据库只能被本地的客户端连接 可见,MySQL官方对skip-grant-tables这个参数的安全问题很重视


除了短连接数暴增可能会带来性能问题外,实际上,在线上碰到更多的是查询或者更新语句导致的性能问题

其中,查询问题比较典型的有两类:


  1. 由新出现的慢查询导致
  2. 由QPS(每秒查询数)突增导致

接下来看看慢查询的这两种典型的问题


二、慢查询性能问题

在MySQL中,会引发性能问题的慢查询,大体有以下三种可能:


  1. 索引没有设计好
  2. SQL语句没写好
  3. MySQL选错了索引

接下来具体分析这三种可能,以及对应的解决方案


2.1 索引没有设计好

导致慢查询的第一种可能是,索引没有设计好,这种场景一般就是通过紧急创建索引来解决


2.2 语句没写好

导致慢查询的第二种可能是,语句没写好,这时可以通过改写SQL语句来处理


2.3 MySQL选错索引

导致慢查询的第三种可能是,MySQL选错索引,这时的应急方案就是给这个语句加上force index


2.4 预先发现问题

上面由慢查询导致性能问题的三种可能情况,实际上出现最多的是前两种, 即:索引没设计好和语句没写好,而这两种情况,恰恰是完全可以避免的

通过下面这个过程,可以预先发现问题


  1. 上线前,在测试环境,把慢查询日志(slow log)打开,并且把long_query_time设置成 0,确保每个语句都会被记录入慢查询日志
  2. 在测试表里插入模拟线上的数据,做一遍回归测试
  3. 观察慢查询日志里每类语句的输出,特别留意Rows_examined字段是否与预期一致

三、QPS突增问题

有时候由于业务突然出现高峰,或者应用程序bug,导致某个语句的QPS突然暴涨,也可能导 致MySQL压力过大,影响服务

由新功能的bug导致这样的情况时,最理想的情况是让业务把这个功能下掉,服务自然就会恢复


3.1 QPS突增处理方式

而下掉一个功能,如果从数据库端处理的话,对应于不同的背景,有不同的方法可用,接下来看看如何处理


  1. 全新业务的bug导致
    假设DB运维是比较规范的,也就是说白名单是一个个加的,这种情况下,如果能够确定业务方会下掉这个功能,只是时间上没那么快,那么就可以从数据库端直接把白名单去掉

  2. 新功能使用单独数据库用户
    如果这个新功能使用的是单独的数据库用户,可以用管理员账号把这个用户删掉,然后断开现有连接
    这样,这个新功能的连接不成功,由它引发的QPS就会变成0

  3. 新功能和主体功能一起
    如果这个新增的功能跟主体功能是部署在一起,那么只能通过处理语句来限制
    这时,可以使用上面提到的查询重写功能,把压力最大的SQL语句直接重写成select 1返回


3.2 风险分析

针对方案三的操作风险极高,而且需要特别细致,还可能存在两个副作用:


  1. 如果别的功能里面也用到了这个SQL语句模板,会有误伤
  2. 很多业务并不是靠这一个语句就能完成逻辑的,所以如果单独把这一个语句以select 1的结 果返回的话,可能会导致后面的业务逻辑一起失败

所以,方案3和前面提到的去掉权限验证一样,应该是所有选项里优先级最低的一个方案

其实方案1和2都要依赖于规范的运维体系:


  • 虚拟化
  • 白名单机制
  • 业务账号分离

由此可见,更多的准备,往往意味着更稳定的系统






推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
aaaa
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有