一:情景

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

  - 在业务高发时候,Mysql 服务压力过大,导致业务受损, 用户的开发负责人说,不管你用什么方案,让业务先跑起来再说。

  - 今天我们就来聊聊这些临时方案,并着重说一说它们可能存在的风险。(有损方案,无损方案肯定不会再这个时候才执行)

二:短连接导致的性能问题

  - 为什么短连接会引起数据库的性能问题?

    - 正常的短连接模式就是连接到数据库后,执行很少的 SQL 语句就断开,下次需要的时候再重连。

    - 在《一条SQL是如何执行的?》 中曾经提到,MySQL 建立连接(需要 TCP 握手,登录权限/数据读写权限 判断)(成本昂贵)。

    - 在数据库压力比较小的时候,这些额外的成本并不明显。

    - 但是,短连接模型存在一个风险,就是一旦数据库处理得慢一些,连接数就会暴涨。(存在于压力大的情况下)

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

      - 超过这个值,系统就会拒绝接下来的连接请求,并报错提示“Too many connections”。

      - 对于被拒绝连接的请求来说,从业务角度看就是数据库不可用。

    - 所以,在机器负载比较高的时候,处理现有请求的时间变长,每个连接保持的时间也更长。

    - 这时,再有新建连接的话,就可能会超过 max_connections 的限制。

  - 为什么不能单纯的通过调高 max_connections 的方式解决短连接过多的问题?

    - 因为设计 max_connections 这个参数的目的是想保护 MySQL.

    - 如果我们把它改得太大,让更多的连接都可以进来,那么系统的负载可能会进一步加大,大量的资源耗费在权限验证等逻辑上.

    - 结果可能是适得其反,已经连接的线程拿不到 CPU 资源去执行业务的 SQL 请求。

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

    - 选择哪些链接断开?

      - Show Processlist 为 sleep 的链接。

      - 你可以优先断开事务外空闲太久的连接(事务表information_schema.INNODB_TRX);

      - 如果这样还不够,再考虑断开事务内空闲太久的连接。

    - 如何断开短连接?

      - 从服务端断开连接使用的是 kill connection + id 的命令。

      - 一个客户端处于 sleep 状态时,它的连接被服务端主动断开后,这个客户端并不会马上知道。

      - 直到客户端在发起下一个请求的时候,才会收到这样的报错“ERROR 2013 (HY000): Lost connection to MySQL server during query”。

    

    - 可能存在的问题?

      - 从数据库端主动断开连接可能是有损的,尤其是有的应用端收到这个错误后,不重新连接,而是直接用这个已经不能用的句柄重试查询。

      - 这会导致从应用端看上去,“MySQL 一直没恢复”。

   第二种方法:减少连接过程的消耗。(取消权限和认证)

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

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

- 但是,这种方法特别符合我们标题里说的“饮鸩止渴”,风险极高,特别不建议使用的方案。尤其你的库外网可访问的话,就更不能这么做了。

三:慢查询导致的性能问题

  - 索引没有设计好

    - 这种场景一般就是通过紧急创建索引来解决。

    - MySQL 5.6 版本以后,创建索引都支持 Online DDL 了。

    - 对于那种高峰期数据库已经被这个语句打挂了的情况,最高效的做法就是直接执行 alter table 语句。

    - 比较理想的是能够在备库先执行。

    - 假设你现在的服务是一主一备,主库 A、备库 B,这个方案的大致流程是这样的:

      - 在备库 B 上执行 set sql_log_bin=off,也就是不写 binlog,然后执行 alter table 语句加上索引;

      - 执行主备切换;

      - 这时候主库是 B,备库是 A。在 A 上执行 set sql_log_bin=off,然后执行 alter table 语句加上索引。

   SQL 语句没写好。

    - 慢查询修复。

   MySQL 选错了索引。

    - 这时候,应急方案就是给这个语句加上 force index。

四:其余的方法

  - 白名单机制

  - 业务账号分离。

五:小结

  - 在实际开发中,我们也要尽量避免一些低效的方法,比如避免大量地使用短连接。

  - 同时,如果你做业务开发的话,要知道,连接异常断开是常有的事,你的代码里要有正确地重连并重试的机制。

  - DBA 虽然可以通过语句重写来暂时处理问题,但是这本身是一个风险高的操作,做好 SQL (explain) 可以减少需要这类操作的机会。

《Mysql - 在Mysql服务出现瓶颈时,有哪些“饮鸩止渴”提高性能的方法?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Control.ImeMode属性简释

    在WINFORM中,我们经常遇到如下问题.文本输入框中输入法有时候需要被禁用,或者某些时候全半角输入自动转换.查阅相关资料,现小结如下. (一)Control.ImeMode 属性:获取或设置控件的输 ...

  2. Chapter Two

    Web容器配置 ~Tomcat配置 server.port配置了Web容器的端口号 error.path配置了当项目出错时跳转去的页面 session.timeout配置了session失效的时间 c ...

  3. [面试]快来测测你的C++水平

    在32位编译环境下进行测试. 以下代码运行结果是什么? #include <iostream> using namespace std; class D { public: static ...

  4. Assignment6:白盒测试方法

    常用的软件测试方法有两大类:静态测试方法和动态测试方法. 其中软件的静态测试不要求在计算机上实际执行所测程序,主要以一些人工的模拟技术对软件进行分析和测试:而软件的动态测试是通过输入一组预先按照一定的 ...

  5. vue+elementui搭建后台管理界面(5递归生成侧栏路由)

    有一个菜单树,顶层菜单下面有多个子菜单,子菜单下还有子菜单... 这时候就要用递归处理 1 定义多级菜单 修改 src/router/index.js 的 / 路由 { path: '/', redi ...

  6. JS 读取 获取 cookie

    alert(document.cookie); cookie 只能获取当前域名的cookie, 该页面的其他域名的获取不了的.

  7. python 画园和椭圆

    from matplotlib.patches import Ellipse, Circle import matplotlib.pyplot as plt fig = plt.figure() ax ...

  8. arcpy显示指定表的索引属性

    import arcpy feature_class = "c:/data/well.shp" # Create a list of indexes using the ListI ...

  9. MySQL there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause同时创建多个更新当前时间戳字段 解决方法

    问题重现 在写这篇文章之前,明确我的MySQL版本,MariaDB 或者你使用 MySQL 8 也会出现如下问题 MySQL 版本 现在有这样的需求,一张表中有一个字段created_at记录创建该条 ...

  10. netty5客户端监测服务端断连后重连

    服务端挂了或者主动拒绝客户端的连接后,客户端不死心,每15秒重连试试,3次都不行就算了.修改下之前的客户端引导类(NettyClient,参见netty5心跳与业务消息分发实例),新增两个成员变量,在 ...