mysql的常见问题

前言

一、mysql有哪些'饮鸩止渴'的提高性能的方法?

二、我为什么改了一行数据,锁这么多?

三、幻读是什么,幻读有什么问题?

四、为什么我只查询一行数据,还是这么慢?

五、为什么mysql语句逻辑相同,执行性能却差异很大

六、如何正确的显示随机数据?


我是一个总标题

一、mysql有哪些'饮鸩止渴'的提高性能的方法?

主要导致需要短时间提高性能的情况有三种,我们根据具体的问题提出对应的解决方案

  1. 短链接风暴,短时间内有大量建立连接的请求,又断开
    1. mysql里面有一个max_connect的参数,用来控制最大链接数量,如果超过这个数量,就会报 too_money_connect 。一种方法是 调高max_connect。但是这会有风险,因为这个参数就是用来保护mysql的,如果有大量的链接进入,可能会导致大量的cpu资源用在了权限校验上,而导致处理业务逻辑的能力下降。
    2. 关闭权限验证,这是一个非常有风险的操作,尤其是你的数据库在外网可访问的情况下。mysql增加了只有本机请求可以通过的命令,可见对与关闭权限验证的重视。
  2. 慢查询
    1. 没有索引导致
      解决方案:创建索引,mysql已经支持线上的DDL操作,如果你的线上库是一主一从,可以现在从库上执行,从库上断开写入redolog然后执行alter。。。 命令,之后切换成主库,然后再在从库上执行
    2. sql有问题导致
      解决方案:使用改写sql的命令,可以将执行的sql模版改写,但是这很可能会产生误伤。
    3. 没有正确使用索引导致
      解决方案:可以通过在命令上添加froce index指定索引,或者也通过重写的方式
  3. QPS突然增加
    1. 业务的暴增或者是新业务的问题导致
      如果是新业务,且白名单是一个一个加的,在明确后期业务会下掉这个功能或者问题的情况下可以通过,删除白名单的方式来解决。
    2. 如果你的新业务是通过新的用户权限来链接数据库的,可以通过删除用户权限来直接让那个qps将为0
    3. 还是上面的重写方法,重写成一个特别简单的sql如:select 1 ,但是极不推荐,因为可能导致后续的所有业务逻辑失败。

二、我为什么改了一行数据,锁这么多?

在msyql的默认隔离级别 可重复读级别下的加锁

有 2个原则 2个优化 1个bug

  • 原则1: 可重复读的隔离级别下,默认的加锁是next-key lock = 记录锁(Record Lock) + 间隙锁(Gap Lock)。
  • 原则2: 只有读到的行才需要加锁
  • 优化1: 在等值查询中,如果条件的是主键索引,会退化成行锁
  • 优化2: 在等值查询中,会向右查询到第一个不满足的位置才停下来,如果最右边不满足,会退化成间隙锁。(为什么会向右,因为在innodb中,默认有序,找到第一个等值之后,系统不确定是否存在第二个等值的情况,所以系统会继续请求下一个值,知道发现大于要比较的值才停止,那么根据优化2就会出现gap lock锁住了等值和大于等值中间的间隙)
  • bug:唯一索引的范围查询会访问到第一个不满足条件的第一个值为止

三、幻读是什么,幻读有什么问题?

幻读是指 在一个session中两次读取数据时,读取到了另一个session插入的数据。

在可重复读的隔离级别下,引入了间隙锁来解决这个问题,间隙锁引入之后,极容易出现两个相同的sql出现死锁的情况:

因为间隙锁之间并不互斥,而是对间隙中插入数据的动作互斥,那么一个线程如果加了间隙锁 另一个也加了。然后就会两个线程谁也写不进去。

如果在读提交的隔离级别下,就不会有间隙锁,但是需要考虑到数据库的内容和binlog的内容不一致的情况。

比如a线程修改了 c=5这条数据的 b =100,而未提交,之后另外两个线程新增了两个c=5的数据,之后a提交了。

那么生成的binlog日志中 最后一条就是 c=5的数据 b全部等于100,就修改了上面所有c=5的数据。当然可以通过修改binlog的记录方式解决。

四、为什么我只查询一行数据,还是这么慢?

  • 第一 这条查询语句被MDL锁住。全称:MataDatalock 元数据锁,用来防止查询的时候,被人修改表结构。MDL锁采用先来后到的机制,一旦MDL写锁出现在等待队列中,那么后面所有的读锁都会被阻塞。
  • 第二 fluse table语句被其它语句阻塞,而fluse语句又阻塞了我们的查询语句。
    • fluse table语句是刷新所有的表,强制关闭重新打开,清理内部缓存,刷新表结构,表数据。
    • 如果已经有查询的请求(默认是持有MDL读锁的),那么fluse table会持有写锁等待,那么我们的查询语句也要等待fluse table执行完成才能继续执行
  • 第三 被行级锁 锁住
  • 第四 查询字段上没有索引,导致全表扫描
  • 第五 在这个事务之前启动的一个事务,在这行数据上进行了很多次操作然后提交,导致我们需要通过mvcc多版本控制忘下找很多版本

五、为什么mysql语句逻辑相同,执行性能却差异很大

大概率是因为破坏了索引的有序性,导致没有使用索引。

  • 一种是使用了函数,函数计算完之后的值在索引上可能无序,导致优化器走主键索引或者覆盖索引。
  • 一种是数据库类型转换 如 utf-8 和utfmb64 由于utfmb64是utf-8的超类,所以执行的时候等于加了类型转换的函数导致无效。其实可以通过避免函数或者该sql不在索引字段上加函数而是再做比较的值上加

六、如何正确的显示随机数据?

msyql返回随机数据的流程是

先把所有数据读到内存中,并给一个权重,然后再根据权重排序 取出前几个作为随机数,所以如果表数据太大,会很慢。

另外rowid就是数据的具体位置,如果有主键 那么主键就是rowid ,如果没有 系统会随机生成

相关推荐
heartbeat..4 小时前
Spring AOP 全面详解(通俗易懂 + 核心知识点 + 完整案例)
java·数据库·spring·aop
麦聪聊数据6 小时前
MySQL并发与锁:从“防止超卖”到排查“死锁”
数据库·sql·mysql
AC赳赳老秦7 小时前
DeepSeek 私有化部署避坑指南:敏感数据本地化处理与合规性检测详解
大数据·开发语言·数据库·人工智能·自动化·php·deepseek
myzshare7 小时前
实战分享:我是如何用SSM框架开发出一个完整项目的
java·mysql·spring cloud·微信小程序
YMatrix 官方技术社区7 小时前
YMatrix 存储引擎解密:MARS3 存储引擎如何超越传统行存、列存实现“时序+分析“场景性能大幅提升?
开发语言·数据库·时序数据库·数据库架构·智慧工厂·存储引擎·ymatrix
辞砚技术录8 小时前
MySQL面试题——索引2nd
数据库·mysql·面试
linweidong8 小时前
C++thread pool(线程池)设计应关注哪些扩展性问题?
java·数据库·c++
墨笔之风9 小时前
java后端根据双数据源进行不同的接口查询
java·开发语言·mysql·postgres
欧亚学术9 小时前
突发!刚刚新增17本期刊被剔除!
数据库·论文·sci·期刊·博士·scopus·发表
黑白极客10 小时前
怎么给字符串字段加索引?日志系统 一条更新语句是怎么执行的
java·数据库·sql·mysql·引擎