MySQL8.0.12 · 引擎特性 · LOB Partial Update优化

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 在之前,笔者介绍过InnoDB对于lob列的更新优化,即允许对lob类型的列数据进行部分更新。由于undo log page本身的限制(例如无法存储过长的数据),对于大列更新,旧版本被留在数据文件中,在MVCC读时,直接从中读旧版本即可。

在之前,笔者介绍过InnoDB对于lob列的更新优化,即允许对lob类型的列数据进行部分更新。由于undo log page本身的限制(例如无法存储过长的数据),对于大列更新,旧版本被留在数据文件中,在MVCC读时,直接从中读旧版本即可。然而对于超长lob列数据,标记删除旧版本再插入完整新数据的开销太大了,尤其是对于json列,通常我们只需要修改其中极少部分的数据。 为了解决这个问题,InnoDB在8.0版本中实现了partial update的概念,将更新的范围缩小到page单位,并对lob Page辅助以索引,每个索引项可以维持一个lob page的多个版本(For MVCC)

WL#11328认为可以对部分更新操作做进一步的优化, 举个简单的例子,一个Page内可能只修改了几十个字节,却需要创建一个新的page,这依然会产生不少的开销,因此在MySQL8.0.12中,对这部分逻辑进行了进一步的优化:当更新少于某个阈值时,采用Undo来记录老的lob数据修改。在需要读数据时,将这部分修改apply到lob列中。根据官方博客中的测试,最多带来了接近三倍的TPS提升,还是相当理想的。

本文主要记录下涉及到的相关代码, 基于MySQL8.0.12。

update

计算更新的字节数

MySQL Server层实际上已经记录了Lob diff,对字段的修改产生的diff维护在Binary_diff_vector中,vector中每个元素类型为Binary_diff,代表对列上的一部分的修改。对一列的更新可能产生多个binary diff。

InnoDB据此信息,去定位到对应的lob数据,InnoDB当前hardcode了一个值LOB_SMALL_CHANGE_THRESHOLD,默认为100字节,当更新的字节数(upd_t::get_total_modified_bytes())小于这个阈值时,走新的逻辑,否则走之前的逻辑(产生一个新的lob page,并递增版本)

写undo

由于在undo中记录的是部分更新,而不是全部Lob数据,undo log的格式需要做一些改动(这意味着升级到8.0.12之后将无法降级到之前的版本), 主要如下:

  • 增加一个flag TRX_UNDO_MODIFY_BLOB, 表示Undo log支持 lob partial update。
  • 新扩展一个byte,用于未来使用
  • 将Binary diffz中存储的老数据(以及对应lob index entry信息)记录入undo log

一个典型的Undo log包含(取自官方博客):

image

ref: trx_undo_page_report_modify

新的修改在记录update vector这里做了扩展,下图取自官方博客:

image

入口函数: trx_undo_report_blob_update

  • 检查所有binary diff的长度是否超过100字节,如果超过了,表明不是small update,则数组长度设置为0,并返回
  • 对于small update,每个binary_diff占用一项,前面提到过一个Lob更新可能包含多个binary diff, 因此每个binary diff都顺序记录到undo log中
  • 而对于一个binary diff,其记录的是数据的修改,但落到数据页上可能横跨两个lob page,这就涉及到最多两个lob index entry,其事务信息同样需要记录下来(lob::get_affected_index_entries)

更新记录

在写完undo之后,需要去更新索引记录,对于Lob列,调用函数 lob::update

  • 当修改的数据长度小于100字节时,走replace_inline(), 即直接修改对应的lob page
  • 否则,调用lob::replace(), 产生新版本的lob page

相关堆栈

lob::update()
|--> replace()
|--> first_page_t::replace_inline()
|--> data_page_t::replace_inline()

Read

根据worklog的描述,新的多去LOB多版本的逻辑变成了如下 (quoted from wl#11328):

1. Let clust_rec point to the latest clustered index record.
2. Using rollptr obtain the undo log record.
3. Construct the update vector from undo log record. 
   Save the update vector (in a queue) related to BLOBs for later use.
4. Using clust_rec and update vector, build older version of clustered
   index record.
5. Let clust_rec point to this version of clustered index record.
6. Check if clust_rec is the version needed.
   If yes, goto (7), otherwise goto (2).
7. Now fetch the BLOBs for clust_rec. Apply the update vectors matching
   the LOB version from the queue.

简而言之,主要是两个步骤:

  1. 从Undo log里读取binary diff信息,并产生update vector
trx_undo_prev_version_build
|-->trx_undo_update_rec_get_update
    |-->trx_undo_read_blob_update

这一步会将读到的数据存到一个lob::undo_vers_t

  1. 如果获得了正确的版本,在返回数据前,将update vector 应用到获得的记录中
row_sel_store_mysql_field_func
|-->lob::undo_vers_t::apply()
    |-->lob::undo_seq_t::apply()
        |-->lob::undo_data_t::apply()

Reference

WL#11328: InnoDB: Optimizing Small Changes to BLOBs
Partial update of JSON values
MySQL 8.0: InnoDB Introduces LOB Index For Faster Updates
MySQL 8.0: New Storage Format for Compressed BLOBs

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
存储 关系型数据库 MySQL
MySQL 8.0特性-自增变量的持久化
【11月更文挑战第8天】在 MySQL 8.0 之前,自增变量(`AUTO_INCREMENT`)的行为在服务器重启后可能会发生变化,导致意外结果。MySQL 8.0 引入了自增变量的持久化特性,将其信息存储在数据字典中,确保重启后的一致性。这提高了开发和管理的稳定性,减少了主键冲突和数据不一致的风险。默认情况下,MySQL 8.0 启用了这一特性,但在升级时需注意行为变化。
|
8天前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
13天前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
40 3
|
15天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
38 1
|
17天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
84 1
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
8天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
23 1
|
10天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
25 4
|
1月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
61 3
Mysql(4)—数据库索引
|
19天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
61 2

相关产品

  • 云数据库 RDS MySQL 版