用从 binlog 中解析出的 id,立即向数据库(主库),会存在查不到的情况吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
WillingXyz
V2EX    程序员

用从 binlog 中解析出的 id,立即向数据库(主库),会存在查不到的情况吗?

  •  
  •   WillingXyz 2021-08-09 20:57:39 +08:00 3011 次点击
    这是一个创建于 1594 天前的主题,其中的信息可能已经有所发展或是发生改变。

    插入数据到数据库,然后监听 binlog,从 binlog 拿新插入的 id 查询数据库,有可能会查不到吗?

    参考下面的文章,这篇文章描述了该场景: https://www.git2get.com/av/109130438.html

    并且工作中也确实遇到过一次(没有从库)。

    上面的文章解释如下: 可以看到发起提交事务后主要经过 3 个阶段:

    1. redo 日志的 prepare 阶段,在这个阶段 innodb 会将 undo, redo 日志进行刷盘;
    2. binlog 的 prepare 和 commit 阶段,这里 binlog 的 prepare 其实什么也没有做,而在 commit 的时候刷新 binlog 到磁盘,在这个时候,其实事务是已经确定要提交了(无论后面是否发生宕机);
    3. redo 日志的 commit 阶段,这个时候会清除 undo 日志,把 redo 日志刷数据盘,也就是 mysql 的存储数据真正落库;

    他认为第二步就写入了 binlog,此时 canal 可以获取到 binlog,但事务还未提交,因为第 3 步还没执行。

    但是在我的理解中,数据是首先写到内存中的,并没有同步写入磁盘,第 3 步只是把 redo log 写入磁盘而已,不会同步写入数据到磁盘中(这里指写入 B+树中)。 所以,mysql 应该可以首先尝试从内存中获取,应该能获取到的吧。

    求大佬解答

    第 1 条附言    2021-08-16 10:42:28 +08:00
    按我的理解,应该是 MVCC 原因。
    在 RC 级别下执行语句时,在语句过程中,只能查询到语句开始时已经提交的事务。
    上面因为第三步没有执行,导致事务未提交,因此查询不到。

    按理说,这种情况应该很少见,就像描述里的那篇文章说的一样,磁盘压力太大可能会导致该问题。
    并且,一般情况下,收到 binlog 后,有一整行的信息,不需要再反查数据库。
    14 条回复    2021-08-11 20:58:38 +08:00
    F281M6Dh8DXpD1g2
        1
    F281M6Dh8DXpD1g2  
       2021-08-09 21:06:38 +08:00
    跟你的隔离级别有关系
    WillingXyz
        2
    WillingXyz  
    OP
       2021-08-09 21:18:02 +08:00
    @liprais 隔离级别是 rc
    zavierx
        3
    zavierx  
       2021-08-09 22:18:23 +08:00
    我理解他的意思是 commit 步骤卡在调用 fsync 函数刷 redo 日志阶段,所以 commit 其实还没有完成。但是此时 binlog 日志已经记录了这个事务了,所以通过这个事务日志的 id 字段查不到还未 commit 完成的记录?
    Ehco1996
        4
    Ehco1996  
       2021-08-10 07:11:11 +08:00
    已经写入到 binlog 中的数据说明事务已经已经被提交了,无论 mysql 有没有落盘,这条记录都是能被查询到的

    redo/undo log 的机制就是在保证就算没落盘宕机了,也不会丢数据

    个人理解可能有不对的地方
    WillingXyz
        5
    WillingXyz  
    OP
       2021-08-10 09:31:34 +08:00
    @Ehco1996 我也是这么理解的,但怎么解释根据 id 查不到的情况呢
    jindeq
        6
    jindeq  
       2021-08-10 10:58:11 +08:00
    @WillingXyz id 是走索引的吧,索引树还没有添加这一条吧?索引跟写入记录是异步的
    WillingXyz
        7
    WillingXyz  
    OP
       2021-08-10 13:33:13 +08:00
    @jindeq 是走索引的。所以我比较困惑,即使第三步提交完成后,也不会同步写索引吧,但第三步提交后肯定可以查到的。
    simonlu9
        8
    simonlu9  
       2021-08-10 19:14:00 +08:00
    写到 binglog 不一定事务已经提交完成,mysql 是两阶段提交了,你读到的可能是 bin_log cache
    Ehco1996
        9
    Ehco1996  
       2021-08-10 19:42:32 +08:00
    @WillingXyz 你说根据 id 查询不到数据,查的是主库还是从库?
    morty0
        10
    morty0  
       2021-08-10 21:06:52 +08:00
    @simonlu9 如果 binlog 不等于事务提交完成, 那 canal 的设计岂不是是有问题的?
    cheng6563
        11
    cheng6563  
       2021-08-11 09:45:10 +08:00
    用 for update 查应该就行了吧。
    cheng6563
        12
    cheng6563  
       2021-08-11 09:49:56 +08:00
    @morty0 就算这样其实也没问题
    binlog 已经是写盘前最后一步了,这两步不原子也没办法解决。
    就算先写盘后写 binlog,也不是原子的还是可能有问题。
    想要更靠谱点大概可以在监听到修改后用 for update 查一次,可保最终一致性。
    WillingXyz
        13
    WillingXyz  
    OP
       2021-08-11 10:35:01 +08:00
    Ehco1996
        14
    Ehco1996  
       2021-08-11 20:58:38 +08:00
    @WillingXyz 不好意思,刚看到标题是从主库读,从主库读的话是不会出现出现这种情况的,一定是事务先提交才会写 binlog (落盘)

    ----

    但是如果是订阅 mysql 的 binlog 的话那又是另外一回事了,如果 mysql 内部采用了两阶段提交( XA )的话
    是有可能先写 binlog,再 commit 的,即你的 slave 订阅者读到一行的写入之后( row write ),马上去主库查询这条 id 的记录,有可能此时 commit 还没被提交( server 的负载过大,还没来得及提交)

    具体我发现了一篇文章讲的还挺好的( https://blog.51cto.com/wangwei007/2323844
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2584 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 07:15 PVG 15:15 LAX 23:15 JFK 02:15
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86