本文主要是为 OB 开发和测试人员提供一些入门建议,分为上中下三篇。本篇主要介绍一些常用参数变量设置,略有难度。在使用 OB 之前阅读,可以起到事半功倍的效果。希望能有帮助,欢迎留言讨论。

参数和变量区别

OB 的参数和变量设置方式常让初学者很迷惘,实际掌握并不难。下面就一点点介绍。

首先说参数和变量的区别。参数(parameter)是 ORACLE 的叫法,变量(variable)是 MySQL 的叫法,在 OB 里这两种概念和修改方法都存在,跟 ORACLE 和 MySQL 基本保持一致。通常集群级别的设置用参数,租户级别的设置用变量。参数查看方式是show parameters,变量查看方式是show [global|session] variables 。在参数或变量的定义中,有初步的涵义说明。

第二说作用域。通常参数的作用域是集群级别,变量的作用域是租户级别。参数和变量通常是针对不同的行为做设置。变量的设置在具体的租户里设置,参数的设置在 sys 租户里设置,影响 sys 的行为就是影响这个集群的行为。所以这并不是说参数的值在所有租户都可以见。

第三还是说作用域。参数的作用域还可以指定生效的节点。默认是所有节点(就是集群级别了)。同时参数的作用域还可以是租户级别,需要指定组户名。这是 sys 租户里参数设置的特权,可以管理其他租户的参数设置。这种效果跟到租户里去设置这个参数效果是一样的(在具体的租户里设置就不需要指定组户名)。

第四说生效时间。大部分参数的设置是立即生效的,极少数参数修改需要重启节点或集群。变量的设置生效时间则有点复杂,取决于变量的设置方法。比如说是租户全局级别设置、会话级别设置、语句级别设置。如果是全局级别的变量设置,老的会话的变量不会变化,只有新建会话的变量设置才会生效;如果是会话级别的变量设置,该会话里立即生效,但是会话断开重连后,所有变量又读取了全局级别的默认变量设置。语句级别的变量设置主要是以 Hint 形式存在,只影响当前语句并是立即生效。

第五说参数的设置方法。参数的设置通常是通过alter system set xxx方式修改,也可以通过节点进程启动时指定(指 observer 启动参数 -o 里指定的)。即使启动时指定了参数,后期也是可以修改的。

第六说变量的设置方法。变量的设置方法通常是通过set [global] xxx方式修改。大部分变量都可以反复修改,极少数变量属于初始化变量(如字符集),只能在实例初始化的时候指定一次,后期不能再修改。还有一招是在 sys 租户里设置其他租户的变量,方法是alter tenant xxx set yyyy,这种效果相当于租户全局级别的变量设置。

第七说参数和变量的持久化。参数的修改会写到sys租户视图__all_virtual_sys_parameter_stat中和observer的参数文件中,下次重启节点时会读取。变量的修改只要是全局级别的修改,都会写到租户的内部视图__all_sys_variable中。


OB 参数配置的场景

OB 对 ORACLE 和 MySQL 的兼容主要是 SQL 语法层面的兼容,其他存储、事务的设计都有 OB 自己的特色。初学者常用使用传统数据库的方式来学习 OB,很可能会遇到一些不必要的问题。这些问题大部分可以通过参数配置(包括变量)来避免。

设置 OB 运行日志

OB 的运行日志在/home/admin/oceanbase/log/下,运行日志有三类,分别为rootservice的日志,election service的日志、observer的日志。每个日志有分为两类,一个是记录日志级别在WARN级别(含)以上的日志,一个是记录所有日志级别在参数syslog_level定义级别(含)以上的日志。

OB 的运行日志的量会非常大,可以设置日志滚动输出,设置每类日志包含的最大文件数等。如果/home/admin/分区空间不大的话,需要设置少一点日志文件,以及提高日志级别。弊端就是 OB 有问题时技术支持需要查看相应运行日志,该日志可能被过早清理掉了。所以这个分区的空间大小建议在 100G 以上。

alter system set enable_syslog_recycle = True; -- 开启日志文件清理
alter system set max_syslog_file_count = 5; -- 保留日志文件的个数。空间少的时候少一点,但是不利于问题排查(有可能导致问题日志被过早的自动清理了)
alter system set syslog_level='WARN'; -- 提高日志级别可以减少日志量,但不利于问题排查
alter system set syslog_io_bandwidth_limit = '10M';
alter system set clog_sync_time_warn_threshold='2s'; -- clog日志同步慢的时候触发debug日志的输出。从默认的'100ms'调整到'2000ms',减少日志中输出的信息

设置租户的超时参数(调优内存使用)

OB 是分布式数据库,为避免并发压力很大时慢 SQL 拖垮数据库性能,OB 可以设置 SQL 语句超时时间(ob_query_timeout,默认值是 10s)。为了避免未提交的事务锁表导致不必要的阻塞和等待,OB 设置事务未提交超时时间(ob_trx_timeout,默认值 120s)和空闲时间(ob_trx_idle_timeout,默认值100s)。在 2.2.5 版本以前,SQL 申请锁的时候也受语句超时时间控制。2.2.5 版本新增一个单独的锁等待超时时间变量(ob_trx_lock_timeout,默认值是 -1 ,表示无限大,向前兼容)。在前文《 ​从ORACLE/MySQL到OceanBase:数据库超时机制》已经详细解释过用法了。

这些超时变量需要在业务租户里设置。

SET GLOBAL ob_trx_idle_timeout=1200000000;
SET GLOBAL ob_trx_timeout=1000000000;
SET GLOBAL ob_trx_lock_timeout=10000000;
SET GLOBAL ob_query_timeout=100000000;

设置集群转储合并

OB 里内存资源是很关键的。开发搭建的 OB 集群的机器内存资源可能很少,使用中很容易碰到内存不足的报错。即使机器内存符合 OB 要求,如果做大批量写测试,也可能会碰到内存不足的错误。

OB 的租户使用了集群的部分资源(包括内存),多少是自定义的。资源不足的时候可以在线扩容,前提是集群的资源池还有余量。默认情况下,租户内存的一半是block cache(存放读取的基线数据,只读保存),一半是memtable内存(存放修改的增量数据)。OB 的写产生的内存脏块默认不落盘。当memtable中脏块比例到达参数 freeze_trigger_percentage(默认值 75%)时会发起转储(checkpoint)。转储会释放memtable中的脏块内存。转储到一定次数后会发起合并(merge),合并时memtable中已提交事务的脏块都跟磁盘上基线数据合并,进而释放大量内存。OB 的内存参数调优就是控制memtable内存的大小和转储速度。参数调优得当的话,内存的释放速度是可以高于内存的消耗速度,不管这个 TPS 有多大(注意不解决大事务问题)。

这些参数需要在sys租户里设置,影响这个跟集群。

alter system set enable_merge_by_turn = false; -- 关闭轮转合并。
alter system set merge_thread_count = 32; -- 增大合并的线程数。
alter system set minor_merge_concurrency = 32; -- 增大转储的线程数,期望提高转储的速度。
alter system set memory_limit_percentage = 90; -- OB占系统总内存的比例,提高OB可用的内存量。
alter system set memstore_limit_percentage = 90; -- memstore占租户的内存比,尽量增大memstore的空间(但是可能对读操作有负面影响)。
alter system set freeze_trigger_percentage = 30; -- 启动major/minor freeze的时机,让转储(minor freeze)尽早启动,memstore内存尽早释放。
alter system set minor_freeze_times = 100; -- minor freeze的次数,尽量不在测试期间触发major freeze。
alter system set minor_warm_up_duration_time = 0; -- 加快minor freeze
alter system set sys_bkgd_io_high_percentage=100; -- 从默认的90调整到100,提高转储的IO使用上限。前提是 IO 性能好。
alter system set sys_bkgd_io_low_percentage=100; -- 从默认的0调整到100,提高转储的IO使用上限。。前提是 IO 性能好。

设置租户内存写入限速

租户的memtable内存消耗过快时,除了加速转储外,还有个策略就是对写的速度限流。

具体有两种思路。一是应用查询租户的memtable内存剩余比例,如果太低,自己降低写入速度。这种多用于datax加载数据到 OB、OMS 迁移数据到 OB 中、以及其他批量写入任务中。
判断租户剩余内存比例的方法如下,在租户内部查询,最后一个
mem_usage就是memtable内存使用比例。

SELECT round(active/1024/1024) active_mb, round(total/1024/1024) total_mb, round(freeze_trigger/1024/1024) freeze_trg_mb, round(mem_limit/1024/1024) mem_limit_mb
, freeze_cnt , round((active/freeze_trigger),2) freeze_pct, round(total/mem_limit, 2) mem_usage
FROM gv$memstore;

另外一种思路就是 OB 内存参数设置限流阈值。这个参数作用范围是租户。可以在sys 租户里设置。

alter system set writing_throttling_trigger_percentage = 95 tenant = 'obbmsql' ; -- 在memstore的内存使用率达到80%时开启写入限速。
alter system set writing_throttling_maximum_duration = '1h' tenant = 'obbmsql'; -- 限速的速率,控制剩余内存最多支持1小时的写入。

也可以在业务租户内部直接设置。

alter system set writing_throttling_trigger_percentage = 95 ; -- 在memstore的内存使用率达到80%时开启写入限速。
alter system set writing_throttling_maximum_duration = '1h' ; -- 限速的速率,控制剩余内存最多支持1小时的写入。

一旦租户memtable内存使用率超过 writing_throttling_trigger_percentage 值,该租户相应的写操作会被挂起,等待事件为 memstore相关。

设置集群支持 prepared statement

C 程序连接 OB 时,应用端开启prepared statement功能时可能会遇到报错

SQLPrepare retcode is SQL_ERROR
error is 600, meeesage is [OceanBase][ODBC 5.3(a) Driver][OceanBase-2.2.0]internal error code, arguments: -4007, while parameter _ob_enable_prepared_statement is disabled, prepared statement not supported, sqlstate is HY000, len is 178

此时需要开启一个内部隐藏参数 _ob_enable_prepared_statement。未来高版本里这个参数应该会转正。

ALTER SYSTEM SET _ob_enable_prepared_statement=TRUE;

设置集群负载均衡行为

OB 的负载均衡设计是 OB 设计最精妙的一个功能。具体可以参考《 ​揭秘OceanBase的弹性伸缩和负载均衡原理》。OB 的负载均衡独特之处是它是通过改变内部数据分区的主副本位置间接来调整各个节点承载的读写请求和存储。负载均衡的过程就是大量分区迁移和切主事件。

针对负载均衡的参数调优就是控制分区迁移时的并行度。可以在速度和稳定性之间取一个平衡。速度最快的时候,后台分区迁移任务可以把网络带宽耗尽。下面是一个建议值。

alter system set enable_rebalance=true;
alter system set enable_auto_leader_switch=true;
alter system set data_copy_concurrency=20;
alter system set server_data_copy_out_concurrency=8;
alter system set server_data_copy_in_concurrency=8;
alter system set sys_bkgd_net_percentage=80;

设置 SQL 并行

OB 设计上是支持 HTAP 场景的。当前版本每个节点对于大查询还是单线程运行的。如果想运行快一些,就要在 SQL 里设置并行数。效果非常明显。如果表非常大,查询不能在 10s 以内返回,那么还需要调整语句超时时间。

SELECT /*+ parallel(16) */ count(*) FROM BIG_TABLE;

这个并行值也不是随意设置的很大,OB 服务端能用于并行查询的线程数也受一些变量限制。需要在业务租户里设置一下

set global ob_sql_work_area_percentage = 30; -- 定义租户的SQL层可使用的内存空间占比
set global parallel_max_servers = 900; -- 提高px可同时并发的线程数上限
set global parallel_servers_target = 900; -- 提高px并行度

设置高可用

OB 的高可用能力是 OB 设计精妙的第二个地方。OB 高可用的前提是每个数据都有三副本,三副本平时通过 PAXOS协议同步事务日志。OB 的高可用粒度是分区(数据的子集),所以切换的时候是按分区切换。OB 的多副本同步没有异步同步这个概念,所以没有参数可以调节这个.这里说的参数是故障后的一些行为调整.

当一个节点掉线后,短时间内 OB 还是认这个节点内部的分区为三副本成员之一。但是长期掉线,三副本缺一(指不可用)也是一件有风险的事情。所以 OB 容忍一个节点离线最长时间由参数server_permanent_offline_time控制。超过这个时间就是永久掉线。OB 会自动在同一个 Zone 的其他节点里去补齐这个故障节点上的分区副本数据(本质就是创建新的备副本,然后从主副本复制数据)。这个前提就是 OB 集群是 2-2-2 布局。对于单副本集群或者只有 3 台机器的 3 副本集群,这个参数没有什么用。如果想观察这个自动补数据行为,可以调小这个参数。

alter system set server_permanent_offline_time='600s';


汇总

上面参数主要是开发测试环境的建议,目的是尽可能的规避因为使用不当而导致的报错。生产环境的参数配置以 OB 交付人员的建议为准。

下面汇总一下所有参数设置,方便直接使用。

集群参数的设置

以下参数在 sys 租户里设置.

alter system set enable_syslog_recycle = True; -- 开启日志文件清理
alter system set max_syslog_file_count = 5; -- 保留日志文件的个数。空间少的时候少一点,但是不利于问题排查(有可能导致问题日志被过早的自动清理了)
alter system set syslog_level='WARN'; -- 提高日志级别可以减少日志量,但不利于问题排查
alter system set syslog_io_bandwidth_limit = '10M';
alter system set clog_sync_time_warn_threshold='2s'; -- clog日志同步慢的时候触发debug日志的输出。从默认的'100ms'调整到'2000ms',减少日志中输出的信息
alter system set enable_merge_by_turn = false; -- 关闭轮转合并。
alter system set merge_thread_count = 32; -- 增大合并的线程数。
alter system set minor_merge_concurrency = 32; -- 增大转储的线程数,期望提高转储的速度。
alter system set memory_limit_percentage = 90; -- OB占系统总内存的比例,提高OB可用的内存量。
alter system set memstore_limit_percentage = 90; -- memstore占租户的内存比,尽量增大memstore的空间(但是可能对读操作有负面影响)。
alter system set freeze_trigger_percentage = 30; -- 启动major/minor freeze的时机,让转储(minor freeze)尽早启动,memstore内存尽早释放。
alter system set minor_freeze_times = 100; -- minor freeze的次数,尽量不在测试期间触发major freeze。
alter system set minor_warm_up_duration_time = 0; -- 加快minor freeze
alter system set sys_bkgd_io_high_percentage=100; -- 从默认的90调整到100,提高转储的IO使用上限。前提是 IO 性能好。
alter system set sys_bkgd_io_low_percentage=100; -- 从默认的0调整到100,提高转储的IO使用上限。。前提是 IO 性能好。

ALTER SYSTEM SET _ob_enable_prepared_statement=TRUE;

alter system set enable_rebalance=true;
alter system set enable_auto_leader_switch=true;
alter system set data_copy_concurrency=20;
alter system set server_data_copy_out_concurrency=8;
alter system set server_data_copy_in_concurrency=8;
alter system set sys_bkgd_net_percentage=80;
alter system set server_permanent_offline_time='600s';

租户参数或变量设置

以下参数和变量在具体的业务租户下设置。

alter system set writing_throttling_trigger_percentage = 95 ; -- 在memstore的内存使用率达到80%时开启写入限速。
alter system set writing_throttling_maximum_duration = '1h' ; -- 限速的速率,控制剩余内存最多支持1小时的写入。

SET GLOBAL recyclebin=off; --关闭数据库对象回收站

SET GLOBAL ob_trx_idle_timeout=1200000000;
SET GLOBAL ob_trx_timeout=1000000000;
SET GLOBAL ob_trx_lock_timeout=10000000;
SET GLOBAL ob_query_timeout=100000000;
SET GLOBAL ob_sql_work_area_percentage = 30; -- 定义租户的SQL层可使用的内存空间占比
SET GLOBAL parallel_max_servers = 900; -- 提高px可同时并发的线程数上限
SET GLOBAL parallel_servers_target = 900; -- 提高px并行度