V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
lasuar
V2EX  ›  MySQL

关于 mysql change buffer 的 update/delete 操作如何获取到 affected rows 的问题

  •  
  •   lasuar · 2021-08-08 13:05:36 +08:00 · 2344 次点击
    这是一个创建于 1195 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我仔仔细细把官网 ChangeBuffer 部分的章节看完了,仍然得不到这个问题的答案;请教知道的大佬解答一下,十分感谢!

    8 条回复    2021-08-10 12:20:17 +08:00
    IamUNICODE
        1
    IamUNICODE  
       2021-08-08 14:59:50 +08:00
    是这个不
    http://mysql.babo.ist/#/en/mysql-affected-rows.html
    lasuar
        2
    lasuar  
    OP
       2021-08-08 18:28:41 +08:00
    @IamUNICODE 这只是解释什么是 affected rows
    IamUNICODE
        3
    IamUNICODE  
       2021-08-08 18:46:17 +08:00
    @lasuar 那个 example 没用么
    crclz
        4
    crclz  
       2021-08-08 22:51:38 +08:00
    我不知道首影响的行数是否与 change buffer 有关(之前不知道 changebuffer 这个概念)。

    但是抛开 change buffer 不谈,可以使用 ROW_COUNT()获取上一条语句( update or delete )影响的行数。
    https://www.cnblogs.com/langtianya/p/4776531.html

    至于具体的代码...你可以让你的连接执行 2 次查询,第一次执行 update 或者 delete,第二次获取 ROW_COUNT()。如果想要一次性拿到,可以看看特定 ORM 的文档。

    例如.net 的 dapper,就可以执行多个 sql,拿到多个结果。https://github.com/DapperLib/Dapper#multiple-results
    louettagfh
        5
    louettagfh  
       2021-08-09 11:24:08 +08:00
    InnoDB 的删除逻辑是先删聚簇索引, 再删除二级索引(标记删除), 所以当主键索引发现 DB_RECORD_NOT_FOUND 就会返回, 所以不会触发缓存不存在的索引数据
    lasuar
        6
    lasuar  
    OP
       2021-08-09 18:11:46 +08:00
    @louettagfh 官文中对于 change buffer 的描述是,它可以缓存所有对于 buffer pool 中不存在的二级索引的 DML 操作,可以不用去读磁盘获取实际数据(是有原话的)。我的疑问就是 update/delete 操作如果不读磁盘怎么可能拿得到 affected rows,换言之,我认为不论是 change buffer 还是 buffer pool,二者之一是一定去读了磁盘的,但不清楚具体逻辑,就很懵逼,全网搜遍也查不到相关资料,我要是会 Cpp 就直接去看源码了。

    你的意思是当 buffer pool 中不存在待修改的二级索引时,innodb 还是会去读磁盘通过 B+树找到页,再找到记录并进行删除(标记),然后再去删除(标记)二级索引。 有相关资料描述这个过程吗?
    louettagfh
        7
    louettagfh  
       2021-08-09 23:33:45 +08:00
    @lasuar

    和 buffer pool 没有关系, buffer pool 不感知 B+ tree.


    删除一条 record, 不可能只删除二级索引,所以 InnoDB 先删除主键索引,再删除二级索引, 所以假如你要删除的 Record 比如 id (主键), age (二级索引) 的时候主键不存在,二级索引也就不用找了.

    修改也同理


    buffer pool 没有聚簇索引的 page 会去读,因为 change buffer 不缓存聚簇索引, 二级索引的 Page 假如符合使用 change buffer 的条件没有的话就不去读,直接使用 change buffer 的 page, change buffer 的 page 是连续分配的. 写入完成后,假如用户的一次查询用到了这个二级索引的 Page,就把二级索引的数据页读上来和 change buffer 的 Page 做一个 merge 操作, 再返回给用户.


    没有相关资料 看源码吧
    lasuar
        8
    lasuar  
    OP
       2021-08-10 12:20:17 +08:00
    @louettagfh 嗯,我昨天想明白了。不管有没有 change buffer,对于不在内存中的聚簇索引页,innodb 都会去读磁盘,然后内存修改聚簇索引页中的元数据,其实这个时候就已经拿到了 affected rows 。

    然后才是轮到索引页的更新,change buffer 是针对索引页更新的优化,我之前没理清楚整个过程。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1048 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 19:41 · PVG 03:41 · LAX 11:41 · JFK 14:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.