我仔仔细细把官网 ChangeBuffer 部分的章节看完了,仍然得不到这个问题的答案;请教知道的大佬解答一下,十分感谢!
1
IamUNICODE 2021-08-08 14:59:50 +08:00
是这个不
http://mysql.babo.ist/#/en/mysql-affected-rows.html |
2
lasuar OP @IamUNICODE 这只是解释什么是 affected rows
|
3
IamUNICODE 2021-08-08 18:46:17 +08:00
@lasuar 那个 example 没用么
|
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 |
5
louettagfh 2021-08-09 11:24:08 +08:00
InnoDB 的删除逻辑是先删聚簇索引, 再删除二级索引(标记删除), 所以当主键索引发现 DB_RECORD_NOT_FOUND 就会返回, 所以不会触发缓存不存在的索引数据
|
6
lasuar OP @louettagfh 官文中对于 change buffer 的描述是,它可以缓存所有对于 buffer pool 中不存在的二级索引的 DML 操作,可以不用去读磁盘获取实际数据(是有原话的)。我的疑问就是 update/delete 操作如果不读磁盘怎么可能拿得到 affected rows,换言之,我认为不论是 change buffer 还是 buffer pool,二者之一是一定去读了磁盘的,但不清楚具体逻辑,就很懵逼,全网搜遍也查不到相关资料,我要是会 Cpp 就直接去看源码了。
你的意思是当 buffer pool 中不存在待修改的二级索引时,innodb 还是会去读磁盘通过 B+树找到页,再找到记录并进行删除(标记),然后再去删除(标记)二级索引。 有相关资料描述这个过程吗? |
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 操作, 再返回给用户. 没有相关资料 看源码吧 |
8
lasuar OP @louettagfh 嗯,我昨天想明白了。不管有没有 change buffer,对于不在内存中的聚簇索引页,innodb 都会去读磁盘,然后内存修改聚簇索引页中的元数据,其实这个时候就已经拿到了 affected rows 。
然后才是轮到索引页的更新,change buffer 是针对索引页更新的优化,我之前没理清楚整个过程。 |