V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
gps32251070
V2EX  ›  程序员

关于面试 MySQL 的疑问

  •  1
     
  •   gps32251070 · 2023-05-31 17:51:21 +08:00 · 3427 次点击
    这是一个创建于 575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近的一次面试,面试官提到了一个 MySQL 场景,如下


    表 t 只有两个字段,主键 id 和 varchar 类型的 name ,现在有一条 SQL:select id,name from t limit 2; 这条语句执行过程中很慢,问大概的原因。


    思考了一下,感觉不是锁问题,所以答了下大概是服务器负载大,查询的 SQL 很多都是不重复的,导致数据页缓存命中有问题之类的,面试官不是很满意这个答案,后面快结束我又问了下这个问题,面试官回答大概意思是负载导致的锁的问题。

    我的疑问是,这个 sql 语句不是走的快照读吗?又没有加 lock in share mode ,其他语句的锁怎么会影响到它的执行呢?还有一个可能是加了 MDL 写锁,但是 MDL 写锁在修改表结构的情况下才会发生,生产环境基本不会出现。有没有懂的老哥帮忙解答下?

    58 条回复    2023-06-01 18:38:38 +08:00
    JasonLaw
        1
    JasonLaw  
       2023-05-31 18:04:41 +08:00   ❤️ 1
    这是一个很傻逼的问题,我想不出任何理由会导致 select id, name from t limit 2 慢。
    JasonLaw
        2
    JasonLaw  
       2023-05-31 18:06:05 +08:00
    ta 说负载导致的锁的问题,那具体是什么呢?什么负载?造成了什么锁?
    bk201
        3
    bk201  
       2023-05-31 18:09:26 +08:00
    select 还能导致锁问题?
    gps32251070
        4
    gps32251070  
    OP
       2023-05-31 18:13:45 +08:00 via iPhone
    @JasonLaw 意思是 mysql 负载大,具体锁没说,就说查询会加锁,我看他不怎么想继续就没细问
    himly1
        5
    himly1  
       2023-05-31 18:15:05 +08:00
    @bk201 会啊,如果有 sql 对当前 sql 涉及的数据加了 X 锁,就会阻塞.
    gps32251070
        6
    gps32251070  
    OP
       2023-05-31 18:18:16 +08:00 via iPhone
    @himly1 这个语句是快照读,没有加任何锁
    liprais
        7
    liprais  
       2023-05-31 18:19:26 +08:00   ❤️ 1
    面试官半瓶子醋,不用搭理他
    himly1
        8
    himly1  
       2023-05-31 18:19:44 +08:00
    可能是 innodb 且负载太大,其中大部分都是写操作,那么就有可能是因为 x 锁导致 select 语句无法读取 s 锁, 导致一直处于阻塞状态,所以会慢。
    gps32251070
        9
    gps32251070  
    OP
       2023-05-31 18:21:19 +08:00 via iPhone
    @himly1 语句没有加 lock in share mode 啊,怎么会加锁
    himly1
        10
    himly1  
       2023-05-31 18:22:50 +08:00
    @gps32251070 学到了
    wangnimabenma
        11
    wangnimabenma  
       2023-05-31 18:26:23 +08:00
    刷脏页会抖一下,但是和这个好像没关系
    admol
        12
    admol  
       2023-05-31 18:31:18 +08:00
    这个 MySQL 45 讲 里面好像有讲到。
    1 、 如果是数据库本身就有很大的压力,那所有的 SQL 都会很慢,不仅是你这个 SQL
    2 、表被锁了(等 MDL 锁、等 flush 、等行锁)
    3 、慢查询(有其他 SQL 影响)
    xuanbg
        13
    xuanbg  
       2023-05-31 18:47:03 +08:00
    就是记录数太多了且没有任何索引。譬如上亿条数据里面查 2 条,也是是全表扫描,自然慢得一逼。
    JasonLaw
        14
    JasonLaw  
       2023-05-31 18:50:02 +08:00
    @xuanbg #13 没有索引也没事吧,它只是找出两条,它不在意总量多大,它的时间复杂度不是 O(n),而是 O(1)。
    gps32251070
        15
    gps32251070  
    OP
       2023-05-31 18:58:17 +08:00 via iPhone
    @xuanbg 没索引也没有任何关系吧,没有任何 where 条件
    gps32251070
        16
    gps32251070  
    OP
       2023-05-31 18:59:29 +08:00 via iPhone
    @xuanbg 而且面试官给我的方向是锁导致的问题
    gps32251070
        17
    gps32251070  
    OP
       2023-05-31 19:03:28 +08:00 via iPhone
    @admol 我考虑到 1 ,3 点了,所以说了数据页问题。第二点 MDL 可能性很低,谁会高并发改表结构?行锁问题这个语句没有加任何锁,所以也不需要等锁吧,快照读
    xuanbg
        18
    xuanbg  
       2023-05-31 19:22:53 +08:00
    @JasonLaw 不信你自己建个表看看执行计划是不是 all 就完了嘛。
    xuanbg
        19
    xuanbg  
       2023-05-31 19:27:47 +08:00
    @gps32251070 没索引不是一定有问题,但记录数多还没索引就遭不住。。。
    gps32251070
        20
    gps32251070  
    OP
       2023-05-31 19:45:57 +08:00 via iPhone
    @xuanbg 忘了补充,面试官给的数据量是 20W ,这数据量不加读锁顺序 limit 2 我想不出导致性能问题的底层原因
    xuanbg
        21
    xuanbg  
       2023-05-31 19:56:36 +08:00
    @gps32251070 limit 2 是顺序读 2 条没错,可顺序怎么来的?不得排序先? 20 万数据没索引你排序一个试试看慢不慢就完了。
    xuanbg
        22
    xuanbg  
       2023-05-31 19:58:40 +08:00
    20 万里取 2 条的意思是先读 20 万,然后取 2 条啊,不是直接取 2 条!
    JasonLaw
        23
    JasonLaw  
       2023-05-31 20:09:20 +08:00   ❤️ 2
    @xuanbg #18 虽然 type 是 ALL ,但是不代表它要扫描所有行。没有 offset 的时候,它只会找出前两行。

    JasonLaw
        24
    JasonLaw  
       2023-05-31 20:10:54 +08:00
    @xuanbg #22 它只需要找出前两行就行了。如果觉得你是对的,麻烦给一下证据。

    wushigejiajia01
        25
    wushigejiajia01  
       2023-05-31 20:27:17 +08:00
    关注一下
    taogen
        26
    taogen  
       2023-05-31 20:37:44 +08:00   ❤️ 2
    @xuanbg explain 中 type=ALL 的意思是全表扫描直到查到符合条件的数据。这里 limit 2 ,且没有 order ,扫到第二条数据的时候就满足要求,然后就返回了。我用 OP 的语句查了我生产数据库中一个 1.2G 的表,瞬间就返回了。
    zengguibo
        27
    zengguibo  
       2023-05-31 20:41:58 +08:00
    最大的可能是锁表了,可以使用 show processlist 看一下
    fredcc
        28
    fredcc  
       2023-05-31 20:43:43 +08:00 via Android
    面试官没提到是什么表引擎吗
    tutudou
        29
    tutudou  
       2023-05-31 20:45:48 +08:00
    数据多了,也会导致慢呀,嘴在他身上,他喜欢说什么就什么好了。
    taogen
        30
    taogen  
       2023-05-31 20:52:37 +08:00
    面试官可能是这个意思:一条看似不可能慢的查询 SQL ,在什么情况下会变慢?
    chaleaochexist
        31
    chaleaochexist  
       2023-05-31 21:18:18 +08:00
    如果数据库服务器的负载较高,例如同时有其他大量查询或者写操作,那么查询的执行时间可能会延长。这可能是因为数据库服务器资源不足,导致查询需要等待资源的可用性。
    chaleaochexist
        32
    chaleaochexist  
       2023-05-31 21:18:31 +08:00
    @chaleaochexist #31 GPT 说的.
    koloonps
        33
    koloonps  
       2023-05-31 21:20:06 +08:00
    mark 下,我之前就遇到过 join 查询结果直接超时,换一台服务器就好的情况
    xiangyuecn
        34
    xiangyuecn  
       2023-05-31 21:26:01 +08:00
    什么负载不负载的,加钱皆可解决🐶 所以,原因是钱给少了
    ccde8259
        35
    ccde8259  
       2023-05-31 21:26:23 +08:00
    意味着执行计划不会有问题的情况下,下层结构会带来哪些可能的问题。
    如果是 InnoDB 的话,首先是 Buffer Pool 本身访问就是需要 Mutex 的,有没有可能是等锁导致的慢呢?
    进一步的,如果 Buffer Pool 没有命中就需要从磁盘拖数据,磁盘 IO 导致的慢呢?
    从磁盘拖回来的数据如果是有问题的,比如刷出来了个 Crash 完以后 LSN 高于 Checkpoint 的脏页,从 Redo-Log 恢复数据导致的慢呢?
    xiaofan2
        36
    xiaofan2  
       2023-05-31 21:29:43 +08:00
    1. 什么执行引擎?
    sadfQED2
        37
    sadfQED2  
       2023-05-31 21:30:01 +08:00 via Android
    @JasonLaw 还真有可能慢,而且是我们线上真实遇到过的问题。我们最终查到的原因是因为我们机房交换机有问题,mysql 和业务服务器通讯过程中出现了丢包,丢包引起一系列问题,最终导致查询很慢。

    面试官问这种目测他们也是遇到这种问题了吧,让他们排查网络问题
    xiaofan2
        38
    xiaofan2  
       2023-05-31 21:30:22 +08:00
    @xiaofan2 继续没说完 2. 什么隔离级别 这些前提什么都没有 感觉问题无从下手啊
    sadfQED2
        39
    sadfQED2  
       2023-05-31 21:33:24 +08:00 via Android
    面试官说了是负载问题,但是没说是什么负载啊,网络 io 打满,传输慢成狗,那无论什么查询都超慢是有可能的。

    而且他也没说是 mysql 自己的问题,网络 io 打满,或者磁盘 io 打满,都有可能
    yianing
        40
    yianing  
       2023-05-31 21:34:05 +08:00 via Android
    MySQL 快照读不加锁
    ModStart
        41
    ModStart  
       2023-05-31 21:34:37 +08:00
    1. 数据量过大:如果表 t 中的数据量非常庞大,那么执行这条 SQL 语句会涉及大量的数据读取操作,导致执行时间变长。
    2. 索引缺失:如果在表 t 上没有合适的索引,数据库系统将需要进行全表扫描来查找满足条件的数据,这会导致执行时间延长。
    3. 硬件性能问题:如果数据库服务器的硬件性能较低,如 CPU 、内存、磁盘速度等方面的限制,可能导致执行 SQL 语句的速度变慢。
    4. 锁竞争:如果在执行这条 SQL 语句的同时,有其他的查询或写操作正在对表 t 进行操作,并且涉及到了相同的数据行,那么就可能发生锁竞争,导致执行速度变慢。
    gps32251070
        42
    gps32251070  
    OP
       2023-05-31 21:35:12 +08:00 via iPhone
    @xiaofan2 innodb ,RR 级别,面试官意思强调是锁导致的,我理解这个语句锁是不会导致慢的,唯一可能的是数据页 buffer 频繁被替换
    gps32251070
        43
    gps32251070  
    OP
       2023-05-31 21:37:13 +08:00 via iPhone
    @sadfQED2 他意思是高负载导致的锁等待
    JasonLaw
        44
    JasonLaw  
       2023-05-31 21:53:26 +08:00
    @sadfQED2 #37 这已经脱离了语句本身,网络不行,什么都会慢。还是那句话,这个题目和面试官都很傻逼。
    hangszhang
        45
    hangszhang  
       2023-05-31 22:15:13 +08:00
    锁表可还行,快照读又不加锁
    doraf
        46
    doraf  
       2023-05-31 22:21:11 +08:00
    也可能有这种情况:
    https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
    SERIALIZABLE 这段,This level is like REPEATABLE READ, but InnoDB implicitly converts all plain SELECT statements to SELECT ... FOR SHARE if autocommit is disabled.
    rekulas
        47
    rekulas  
       2023-05-31 23:25:21 +08:00
    锁导致的问题。。。有没可能是这样
    面试官也是技术,内部系统某些逻辑设计不合理为了避免冲突直接锁表更新数据,完了再解锁
    负载上来之后面试官发现这样的频繁加解锁操作会导致 select 明显变慢,一时狂喜,又发现一个 mysql 缺陷,于是用来作为考题测试来面试的“小白”们能否快速分析出原因
    urnoob
        48
    urnoob  
       2023-05-31 23:32:09 +08:00 via Android
    首先说没索引导致肯定不对,因为主键默认就是索引的。
    除了网络等外部情况,可能性最大的是大量比当前 id 还小的数据插入,特别是插入的 id 还是递减的,导致树最左边的节点在不断分裂,一直会有锁。
    yagamil
        49
    yagamil  
       2023-06-01 00:11:49 +08:00
    可能是索引 id 是乱序的? 然后面试其实想考的 limit x,y ; 在数量巨大的情况下的性能问题?
    Weixiao0725
        50
    Weixiao0725  
       2023-06-01 00:22:18 +08:00
    要我回答就说这个 mysql 一定是运行在 20 年前的机器上
    Euthpic
        51
    Euthpic  
       2023-06-01 01:36:46 +08:00 via Android   ❤️ 1
    这个问题有点傻 x ,因为慢的原因和 sql 无关,原因可能出在 mysql ,网络,硬盘等系统方面。给出具体 sql 的目的是觉得这个 sql 可以优化吗?
    nuk
        52
    nuk  
       2023-06-01 03:01:29 +08:00
    遇到过两种情况,一种是卡 io ,还有一种很奇怪,是某个客户端执行语句,sql 协议出问题,一直在等几个 byte ,然后整个表就处于锁死的状态。
    akira
        53
    akira  
       2023-06-01 05:33:53 +08:00   ❤️ 1
    其实问题是问,一个明显不可能慢的 sql 执行很慢,有什么可能。
    dog82
        54
    dog82  
       2023-06-01 09:19:04 +08:00
    如果 mysql 的事务隔离级别被设置成串行化,会频繁出现!
    但是谁傻到设置成串行化呢
    leorealman
        55
    leorealman  
       2023-06-01 09:46:09 +08:00
    磁盘 IO 被打满是可能会这样的
    plutome
        56
    plutome  
       2023-06-01 10:29:48 +08:00
    @xuanbg

    “ 20 万里取 2 条的意思是先读 20 万,然后取 2 条啊,不是直接取 2 条!”
    “ limit 2 是顺序读 2 条没错,可顺序怎么来的?不得排序先?”

    虽然我自己也经常犯这种“眼高手低”的错误,但是这两句话说得还是离谱。 可能还是要多学习一下。
    Pythoner666666
        57
    Pythoner666666  
       2023-06-01 13:54:24 +08:00
    @xuanbg 兄弟 这个说法就很离谱啊 ,你一边让别人去尝试,可是你自己就是不去真的尝试一下
    8355
        58
    8355  
       2023-06-01 18:38:38 +08:00
    可能是面试官沟通能力有问题.
    这样问法绝大部分正常人的理解应该是在场景正常的情况下因为这条 sql 本身执行慢是什么原因,
    如果说因为其他原因的慢是过于开放性的答案了.面试官应该给予合理引导.

    可以从负载和 io 上回答 也可以从锁上回答. 也可以从各种不合理应用回答.
    也可以从数据量上回答,也可以从表引擎上回答,也可以从数据库配置回答
    还可以通过网络原因上回答.
    都他妈可能影响慢.🤡
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4426 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 01:05 · PVG 09:05 · LAX 17:05 · JFK 20:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.