作者:杨涛涛
资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
之前在学习 OBCP 的培训材料时,有一项名为 BUFFER 表的解释,当时也没太在意(主要是 OBCP 考试里没有涉及到),之后当别人考我时,我 ……!
什么是BUFFER 表(OceanBase 里也叫 Queuing 表)?之前我以为 BUFFER 表就是全局临时表或者说是类似 MySQL 一次性整体导入的 MyISAM 表,对这类表的操作无非是划出一块内存区域对其进行读写,来避免频繁的 IO 操作。经过查阅 OceanBase 官方文档后,这个 BUFFER 表并非我理解的那样(我的理解完全错误)。
所谓 BUFFER 表指的是某张表(表记录数可能并不多)被频繁的全量更新(所有记录被执行批量 DML 操作)、按一定比率更新(比如20%的记录被执行批量DML操作),短时间又对这张表进行全量检索,性能急剧下降或者说比之前性能有明显降低的这样一种现象。对于 OceanBase 来讲,对表的 DML 操作都是只打标记(比如 UPDATE ,变为 DELETE 打标记+INSERT),后台再慢慢异步清理旧的数据。所以必然会在更新频率过快并且后台线程清理数据不及时导致的严重读写放大问题、或者统计信息严重不准确(OceanBase 统计信息在合并时触发)导致的执行计划非最优的问题,最终影响检索性能。
可以通过如下操作来进行补救:
- 绑定执行计划,人为引导优化器选择最优执行路径。 比如创建 OUTLINE 让 SQL 语句绑定固定执行计划。
- 手工进行转储或者合并来清理无用数据。
- 给表加属性 table_mode=’queuing’ 。 这个属性是 OceanBase 专门为 BUFFER 表做的优化,具体流程简单概述为:当 BUFFER 表更新记录数超过一定阈值时,自动对这张表进行单独转储以消除大量无效检索,从而实现对 BUFFER 表的快速检索。这个表属性针对 MySQL 租户和 Oracle 租户都有效。Oracle 租户可以自定义 BUFFER 表转储阈值:一个是触发基于全量数据的转储百分比(_ob_queuing_fast_freeze_min_threshold);另外一个是触发快速转储的记录数(_ob_queuing_fast_freeze_min_count)。MySQL 租户目前没看到对应配置项,但是其对BUFFER表的批量更新请求,后台也会有对应的转储操作(对应表:gv$merge_info)。
比如在 MySQL 、Oracle 租户下都创建一张表t2,指定表 table_mode=’queuing’ 。
<mysql:5.6.25:ytt>create table t2 (id int primary key, r1 int,r2 varchar(100)) table_mode='queuing'; Query OK, 0 rows affected (0.032 sec)
MySQL 租户下执行下面语句:
<mysql:5.6.25:ytt>insert into t2 with recursive tmp(a,b,c) as (select 1,1,'mysql' union all select a+1,ceil(rand()*200),'actionsky' from tmp where a < 20000) select * from tmp; Query OK, 20000 rows affected (0.916 sec) Records: 20000 Duplicates: 0 Warnings: 0 <mysql:5.6.25:ytt>delete from t2; Query OK, 20000 rows affected (0.056 sec)
Oracle 租户下可以执行下面语句:
<mysql:5.6.25:SYS>insert into t2 select level,100,'oracle' from dual connect by level <=20000;delete from t2;Query OK, 20000 rows affected (0.070 sec)Records: 20000 Duplicates: 0 Warnings: 0Query OK, 20000 rows affected (0.088 sec)
多次执行上面这些语句后,可以在sys租户下查看MySQL租户、Oracle租户后台针对表t2的单独转储记录:字段 action 为 buf minor merge 的行。
<mysql:5.6.25:oceanbase>SELECT * -> FROM -> (SELECT c.tenant_name, -> a.table_name, -> d.type, -> d.action, -> d.version, -> d.start_time -> FROM __all_virtual_table a -> JOIN __all_virtual_meta_table b using(table_id) -> JOIN __all_tenant c -> ON (b.tenant_id=c.tenant_id) -> AND c.tenant_name in ('mysql','oracle') -> JOIN gv$merge_info d -> ON d.table_id =a.table_id -> where d.action like 'buf minor merge' -> ORDER BY d.start_time DESC limit 2 ) T -> ORDER BY start_time asc; +-------------+------------+-------+-----------------+------------------+----------------------------+ | tenant_name | table_name | type | action | version | start_time | +-------------+------------+-------+-----------------+------------------+----------------------------+ | mysql | t2 | minor | buf minor merge | 1678867962096191 | 2023-03-15 16:13:14.774809 | | oracle | T2 | minor | buf minor merge | 1678871458311991 | 2023-03-15 17:11:38.426437 | +-------------+------------+-------+-----------------+------------------+----------------------------+ 2 rows in set (0.008 sec)