针对MySQL在高并发环境下写入BLOB(二进制大对象)时常见的锁竞争和Redo日志瓶颈,PolarDB通过内核级优化,有效解决了BLOB写入过程中的锁争用、I/O压力及空间管理等问题,显著提升了DML和DDL操作的性能,确保您的业务在高并发场景下稳定高效地运行。
功能简介
BLOB(Binary Large Object)是数据库中用于存储图片、文档、长文本等大尺寸数据的字段类型。在原生MySQL InnoDB引擎中,当数据行中的BLOB字段超过特定大小时,会将其存储在独立的外部数据页(Off-Page)中。这种机制虽然能处理大数据,但也带来了三大性能挑战:
并发写入瓶颈:更新外部页时会触发悲观锁,导致同一时间内单表只允许一个线程执行BLOB写入,严重限制了并发能力。
I/O压力剧增:大字段会产生体积庞大的Redo日志,如果磁盘I/O能力不足,日志刷写将成为瓶颈,阻塞前台写入。
空间回收延迟:旧版本BLOB数据的清理(Purge)效率不高,可能导致存储空间膨胀和性能下降。
PolarDB的BLOB优化功能正是为了解决上述问题,它在不改变您使用习惯的前提下,从内核层面对BLOB的写入、更新和回收全链路进行优化。
计费说明
BLOB性能优化功能均为PolarDB内核自带功能,不收取任何费用。
优化BLOB写入性能
如果您在业务高峰期遇到BLOB表的写入吞吐量瓶颈、并发写入时延高的问题,通常是由于写入锁竞争导致的。PolarDB提供了预分配页和索引锁(Latch)优化来解决此问题。
预分配页优化
该优化将BLOB的写入过程分解为以下几个步骤:
计算并一次性批量申请好所需的全部数据页。
在无锁状态下完成数据拷贝,将BLOB内容填充到新申请的页中。
通过一次乐观锁操作,将生成的数据页链表挂载到索引记录上。
在整个写入过程中,只有初始的空间申请阶段是互斥的,其余耗时较长的数据拷贝等操作均允许其他BLOB写入并发进行。此外,由于数据拷贝是在非临界区完成,系统可以避免因单次写入产生大量Redo日志而占满缓冲区、导致写入被阻塞的风险。最终,该机制将全局锁的持有时间降至最低,从而大幅提升了并发写入能力。
索引锁(Latch)优化
对于包含小尺寸(8 KB以下)或混合尺寸BLOB字段的表,原生MySQL在更新时,常因索引页结构变更(SMO)而过早地放弃乐观锁,退化为低效的悲观锁模式,严重影响并发性能。Latch优化通过在乐观路径下完成更多工作,解决了这一瓶颈。该优化按以下步骤工作:
保持乐观路径:当检测到可能需要更新BLOB字段时,优化逻辑并不会立即切换到悲观锁。它会继续持有冲突概率更低的共享锁(S-latch),保持在乐观更新路径。
预先构建并尝试更新:在乐观路径下,它会预先构建更新所需的BLOB数据结构,并尝试直接对索引页进行修改。
判断与提交/回退:
成功:更新后的记录能够满足当前索引页的空间要求,操作便在乐观路径下快速完成。
失败:例如页面空间不足,优化会自动放弃本次尝试,并无缝回退到原生MySQL的悲观锁路径,由其完成整个更新操作,确保数据的一致性。
这种乐观尝试的机制,其核心优势在于显著提高了乐观更新的成功率。它使得大量原本会退化为悲观锁的操作,能够以更轻量、更高效的方式完成,从而大幅提升了在高并发下更新混合尺寸BLOB数据的吞吐能力。
开启写入优化
您可以前往PolarDB控制台的 页面来查看并修改以下参数来开启优化:
参数 | 说明 | 支持版本 |
| 开启或关闭BLOB预分配页优化。 取值范围:
|
|
| 设置BLOB预分配页优化中单个BLOB列的最大长度。 | |
| 开启或关闭BLOB索引锁(Latch)优化。 |
降低BLOB写入的Redo日志量
如果您的业务写入大量BLOB数据,导致Redo日志产生速度过快,成为系统I/O瓶颈,您可以通过开启Redo压缩功能来缓解压力。
Redo压缩是指在将BLOB相关的Redo日志写入日志缓冲区(Log Buffer)之前,对其进行并行压缩。这一过程能够显著减少Redo日志的实际写入量(根据测试效果平均减少40%-60%),从而降低存储I/O的压力,避免因Redo模块瓶颈对整体写入性能产生影响。在数据库进行崩溃恢复时,会自动解压并应用这些日志。
开启Redo压缩
您可以前往PolarDB控制台的 页面来查看并修改以下参数来开启优化:
参数 | 说明 | 支持版本 |
| 设置BLOB的Redo的压缩算法。取值范围:
|
|
| 设置所选压缩算法的压缩级别。 取值范围:0~9,默认值为6。 |
加速删除BLOB空间回收
若您在频繁删除或更新BLOB数据后,发现表空间回收缓慢、文件持续膨胀,其根源在于原生MySQL的后台Purge进程效率低下。该进程在清理数据时,会先持有Index SX
等核心锁再读取BLOB页面。如果页面不在内存中,就会在锁的保护下触发耗时的磁盘I/O操作,从而长时间阻塞表上的其他并发操作。PolarDB的Purge页预读优化通过将I/O操作与加锁过程分离,解决了这一瓶颈。该优化按以下步骤工作:
识别目标页:在正式加锁并开始清理之前,Purge进程会首先识别出需要回收的完整BLOB外部页链表。
异步预读:发起异步I/O请求,将那些尚未在内存中的目标页面提前从磁盘加载到缓冲池(Buffer Pool)中。
快速清理:当所有页面都已加载到内存后,Purge进程才会获取
Index SX
等核心锁,并快速地执行纯内存中的页面释放和元数据修改操作。
Purge页预读机制主要避免了在持有锁的临界区内发生任何磁盘I/O操作。通过将耗时最长的I/O操作前置,使得锁的持有时间被缩短到仅剩快速的内存操作部分。这不仅提升了BLOB数据的回收效率,防止了空间膨胀,更重要的是减少了后台清理对前台业务(如高并发写入)的阻塞,从而提升了整个数据库的并发性能和稳定性。
开启Purge预读
您可以前往PolarDB控制台的 页面来查看并修改以下参数来开启优化:
参数 | 说明 | 支持版本 |
| 开启或关闭BLOB Purge过程中的页预读优化。 取值范围:
| 全版本支持。 |
提升DDL执行效率
如果您需要对包含大量BLOB数据的表执行DDL操作(如ALTER TABLE
),并且耗时过长,可以通过开启DDL相关的BLOB优化来大幅缩短操作时间。
预分配页优化:由于BLOB字段的溢出列会在主键上存在,因此在执行主表重建(rebuild)的DDL操作时,会涉及到BLOB字段的写入。预分配页优化采用了一种更为直接和简化的加锁方式来写入BLOB数据,从而避免了处理复杂并发冲突的开销,显著提升了重建效率。
Latch优化:由于并行DDL会将主键树切分,多个工作线程不会操作同一个数据页。该优化将分配新页的操作独立保护,使得其他操作可以并发执行,提升效率。
Redo优化:
页面聚合:在批量加载(bulk load)数据时,不再为每条记录生成Redo,而是在一个数据页写满后,将整个页面的变更作为一条大的Redo记录写入,提升Redo操作效率。
聚合压缩:对上述聚合后的大块Redo进行压缩,进一步降低DDL过程中的Redo日志量。
开启DDL优化
您可以前往PolarDB控制台的 页面来查看并修改以下参数来开启优化:
以下表格中部分参数暂不支持您手动修改。若您有相关需求,请提交工单联系我们处理。
参数 | 说明 | 支持版本 |
| 在DDL过程中是否开启大字段优化。取值范围如下:
|
|
| 在DDL过程中是否开启索引锁优化。取值范围如下:
|
|
| 在DDL批量加载时是否开启Redo页面聚合。取值范围如下:
|
|
| 设置DDL批量加载时的Redo压缩算法。取值范围:
|
|
| 设置DDL过程中Redo压缩的应用目标。取值范围:
|
|
相关模块优化
在大吞吐量的BLOB操作场景下,系统瓶颈也可能出现在其他模块。为了获得更佳的性能,PolarDB同时结合其他优化措施:
并行Redo异步写入:将Redo Buffer中的数据分片,通过多个线程并发地发出异步I/O任务,大幅提升Redo日志的写入吞吐能力(实测可达4 GB/s)。
文件扩展优化:基于PolarDB的自研分布式文件系统,表空间扩展操作仅需修改少量元数据,并去除了原生的文件填0操作,使文件扩展的耗时和锁开销不再成为瓶颈。
无锁刷脏:采用Shadow Page技术,在刷脏页时先构建内存副本,释放页锁后再用副本进行I/O操作,避免了因刷脏持有页锁而阻塞写入请求。
性能测试数据
以下数据显示了开启 BLOB优化后在DML和DDL场景下的性能提升。
DML性能 在高并发场景下,针对100 KB和200 KB行长的插入和更新,PolarDB的优化方案能带来近3倍的性能提升。结合Redo压缩后,性能可提升4-5倍。
DDL性能 对于一张40 GB的含BLOB字段的表,开启优化后,DDL写入速率提升5-6倍,总耗时下降 84%。