V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
leavan
V2EX  ›  数据库

mysql 里,如果没有用事务直接 select 会脏读吗?

  •  
  •   leavan · 2021-03-18 18:13:12 +08:00 · 1977 次点击
    这是一个创建于 1378 天前的主题,其中的信息可能已经有所发展或是发生改变。

    听说普通的 select 不对数据加锁,那岂不是很容易读到某些事务未提交的数据,应该全用 select ... for update ?

    22 条回复    2021-03-19 17:01:25 +08:00
    ferock
        1
    ferock  
       2021-03-18 18:14:49 +08:00
    可以修改事物隔离级别
    leavan
        2
    leavan  
    OP
       2021-03-18 18:16:04 +08:00
    @ferock 修改了之后呢,mysql 会对普通 select 加锁吗?
    nolo
        3
    nolo  
       2021-03-18 18:19:26 +08:00   ❤️ 2
    1 、select 也会对数据加锁,读锁。一个简单的现象,你在 select 的时候,ddl 会等待 select 结束。
    2 、innodb 支持的四种事务隔离级别,只有 Read Uncommitted 会读到事务未提交的数据。
    leavan
        4
    leavan  
    OP
       2021-03-18 18:22:33 +08:00
    @nolo 好的,感谢!
    hehe12980
        5
    hehe12980  
       2021-03-18 18:23:04 +08:00   ❤️ 1
    现在都是 innodb 引擎,在 innodb 下,你 mysql 的普通读 select 是快照读,压根不会加锁,不管是行读锁还是行写锁都不会影响普通 select,快照读会根据 MVCC 版本链 和 read view 去做判断 不会出现读到 某些事物未提交的情况,当然你的事物隔离级别必须是读已提交以上
    killergun
        6
    killergun  
       2021-03-18 18:24:24 +08:00
    select 在默认情况下都是快照读
    leavan
        7
    leavan  
    OP
       2021-03-18 18:26:23 +08:00
    @hehe12980 啊,也就是不加锁就是靠的 MVCC 控制的普通 select,那这样确实也不会脏读
    hehe12980
        8
    hehe12980  
       2021-03-18 18:32:28 +08:00
    @leavan 嗯,你可以详细了解一下 MVCC,如果读还要加锁,那 mysql 的性能可想而知
    leavan
        9
    leavan  
    OP
       2021-03-18 18:33:18 +08:00
    @hehe12980 好的,感谢!
    leavan
        10
    leavan  
    OP
       2021-03-18 18:34:12 +08:00
    @hehe12980 那三楼说的 select 的时候 ddl 会等待锁住的应该不是数据而是表的元数据?
    hehe12980
        11
    hehe12980  
       2021-03-18 18:40:49 +08:00
    顺便说一句,你说的 select xx for update, 应该是这么一个场景,在我读的时候过程中, 假设有数据正在写并且没有提交,那我要保证我读的是最新的数据,我等到写的事务提交后再读。但是你用快照读也就是普通 select 可能就读不到,正在写但没有提交的这个事物,因为你在我读之前你没有提交,假设这个写的动作很长,在普通 selelct 读完之后,那么他相当于一个未来的事物,我 select 的时候完全不需要关系你未来是怎么变的,我只对当前的操作负责,但是如果你 for update 不会,它会傻傻的等着你写完。
    hehe12980
        12
    hehe12980  
       2021-03-18 18:43:35 +08:00
    @leavan 3 楼说的不对 以我为准就好 欢迎打脸
    leavan
        13
    leavan  
    OP
       2021-03-18 18:47:36 +08:00
    @hehe12980 好的,我现在完全理解了,非常感谢~
    pisc
        14
    pisc  
       2021-03-19 08:17:30 +08:00 via Android
    @hehe12980 这。。。你 select for update 写了这么多,本质上和普通的 select 有个锁而已,搞得这么复杂,
    pisc
        15
    pisc  
       2021-03-19 08:23:36 +08:00 via Android
    @hehe12980 而且,解决的场景也不是你说的场景,而是拿来解决写倾斜之类的问题
    hehe12980
        16
    hehe12980  
       2021-03-19 09:43:55 +08:00
    @pisc 你还不如干脆说多了个 for update,更简洁明了,嫌别人解释的不好你来解释,让我学习学习
    pedia
        17
    pedia  
       2021-03-19 10:57:50 +08:00
    @leavan select 默认不会加锁, 是快照读. MVCC 可以保证. @nolo 3 楼说的 DDL 阻塞 select 是因为 DDL 会对表 加 X 锁,禁止读写.
    nycbdwss
        18
    nycbdwss  
       2021-03-19 11:09:07 +08:00
    https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/83005823

    这篇文章看完 你就知道了 建议看完 真的有用
    hehe12980
        19
    hehe12980  
       2021-03-19 16:12:18 +08:00
    @pedia DDL 的时候 你快照读 读不了么 ????? 怎么会禁止读呢
    pedia
        20
    pedia  
       2021-03-19 16:35:16 +08:00
    @hehe12980 需要我给你翻代码吗? MySQL 的 DDL 有一个升降锁的过程,加 X 锁的时候全都不能读写.
    hehe12980
        21
    hehe12980  
       2021-03-19 16:53:57 +08:00
    @pedia 关掉自动 commit, 然后开两个 session 就能试出来,没那么麻烦,X 锁禁止当前读 也就是你的读 得加锁了,那确实写的时候会读被阻塞了,普通的快照读不会被影响到
    pedia
        22
    pedia  
       2021-03-19 17:01:25 +08:00
    @hehe12980 DDL 的升降锁过程手动启 session 是很难能卡在临界点的, 8.0 的 DDL 是 atomic DDL, prepare 和 commit 阶段都是阻塞读写的,包括你说的快照读.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5995 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 02:15 · PVG 10:15 · LAX 18:15 · JFK 21:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.