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

简介: 在之前,笔者介绍过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.

简而言之,主要是两个步骤:
a. 从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

b. 如果获得了正确的版本,在返回数据前,将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

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
3月前
|
SQL 存储 关系型数据库
MySQL内存引擎:Memory存储引擎的适用场景
MySQL Memory存储引擎将数据存储在内存中,提供极速读写性能,适用于会话存储、临时数据处理、高速缓存和实时统计等场景。但其数据在服务器重启后会丢失,不适合持久化存储、大容量数据及高并发写入场景。本文深入解析其特性、原理、适用场景与限制,并提供性能优化技巧及替代方案比较,助你合理利用这一“内存闪电”。
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
791 152
|
3月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
6月前
|
SQL 缓存 关系型数据库
MySQL 慢查询是怎样优化的
本文深入解析了MySQL查询速度变慢的原因及优化策略,涵盖查询缓存、执行流程、SQL优化、执行计划分析(如EXPLAIN)、查询状态查看等内容,帮助开发者快速定位并解决慢查询问题。
266 0
|
3月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
3月前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
153 15
|
4月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
226 6
|
3月前
|
关系型数据库 MySQL 数据库
MySql事务以及事务的四大特性
事务是数据库操作的基本单元,具有ACID四大特性:原子性、一致性、隔离性、持久性。它确保数据的正确性与完整性。并发事务可能引发脏读、不可重复读、幻读等问题,数据库通过不同隔离级别(如读未提交、读已提交、可重复读、串行化)加以解决。MySQL默认使用可重复读级别。高隔离级别虽能更好处理并发问题,但会降低性能。
173 0
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
|
5月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
146 2

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多