近期打算写一个【从ORACLE/MySQL到OceanBase】序列。本文是第三篇。前期直播回放请到:https://cs.enmotech.com/course/play/17 。

概述

OceanBase和ORACLE一样, 定位都是通用的关系型数据库。然而客户业务场景、环境总是千差万别。数据库如果支持参数在不同客户的环境和需求下最大化发挥自身优势则是个很好的选择。OceanBase也有这样的设计满足用户对OceanBase进行调优的需求。

OceanBase里的参数就影响范围分集群级别和租户级别两类。

OB集群参数的设计参照ORACLE的参数(即parameters) 。OB的租户别名是实例,跟实际机器是解耦的,租户的参数参照MySQL实例的做法又叫变量(variables)。光研究OceanBase的参数和变量就可以感受到这是一个功能强大又非常有趣的数据库。

下面就一一介绍OB使用过程中可能用到的参数和变量。

集群参数

查看和修改参数

首先查看集群参数是需要登录到sys租户里。用户名:root@sys#集群名

  • 查看参数语法如下:

show parameters;​​show parameters like '%limit%';​​show parameters​​where name in ('clog_disk_usage_limit_percentage',​​'data_disk_usage_limit_percentage',​​'resource_hard_limit',​​'resource_soft_limit',​​'memstore_limit_percentage',​​'memory_limit_percentage',​​'sql_audit_memory_limit',​​'memory_limit',​​'major_freeze_duty_time',​​'minor_freeze_times',​​'freeze_trigger_percentage',​​'enable_sql_audit',​​'sql_audit_queue_size',​​'sql_audit_memory_limit',​​'enable_rebalance'​​);



从ORACLE/MySQL到OceanBase:参数或变量_默认值


从上面可以看出几个特点:参数有名称、默认值和描述,以及生效方法(是否需要重启)、生效节点(IPPort)、参数归属模块,是否可见等。每个参数在每个节点上都有一份,其值默认一样可以不一样。

  • 修改参数语法

目前修改参数支持集群所有节点同时修改或者只改某几个节点。

alter system set minor_freeze_times=100;​​alter system set freeze_trigger_percentage=75 server='11.***.84.132:2882';    

从ORACLE/MySQL到OceanBase:参数或变量_默认值_02


参数文件

跟ORACLE一样的是,OceanBase集群参数修改后也会立即持久化到本地参数文件里。这个参数文件对集群启动非常重要,所以OceanBase提供多重路径保存这个参数。类似于ORACLE保存数据库控制文件一样。而这个多重路径也是参数config_additional_dir 指定的。

show parameters like '%config_additional_dir%';

从ORACLE/MySQL到OceanBase:参数或变量_默认值_03


参数文件名叫:observer.config.bin,文件类型是二进制格式,不能直接编辑或用查看,需要用 strings命令查看。这点跟ORACLE的pfile不一样。

$file observer.config.bin​​observer.config.bin: data​​$strings observer.config.bin|egrep "minor_freeze_times|freeze_trigger_percentage"​​minor_freeze_times=100​​freeze_trigger_percentage=75​​

所以,修改每个节点的参数文件的方法通常是在集群里用命令修改。每次修改后,参数文件都会保留上一个版本在文件observer.config.bin.history里,以避免参数修改错误导致集群启动失败。

细心的人可能还会有个问题,参数文件是保存在多个目录的,但是参数目录又要先指定参数。如果是在集群里指定,得先OBServer进程启动,而进程既然启动了说明又先有参数文件了。而这个参数文件不能编辑,最初是不存在的。这里有个“先有鸡还是先有蛋”的问题。

所以上面列举的大部分参数是可以在OBServer启动时指定。如果没有指定就用默认值。

cd /home/admin/node1/oceanbase && /home/admin/node1/oceanbase/bin/observer -i eth0 -P 2882 -p 2881 -z zone1 -d /home/admin/node1/oceanbase/store/obdemo -r '192.168.1.241:2882:2881;192.168.1.81:2882:2881;192.168.1.86:2882:2881' -c 20190423 -n obdemo -o "cpu_count=24,memory_limit=100G,datafile_size=200G,config_additional_dir=/data/data/1/obdemo/etc3;/data/log/log1/obdemo/etc2"

其中 -o 就是用于覆盖OB集群参数的默认值。一旦OBServer进程启动成功后,三个参数文件就生成了。

进程启动参数解释

上面进程启动参数有多个,多跟资源有关。这里一一解释一下,应该能解答对前文《OceanBase数据库实践入门——手动搭建OceanBase集群》里的一些疑惑。

  • config_additional_dir:参数冗余目录。已经解释过。
  • cpu_count:指定OS的逻辑CPU个数。通常不指定的时候,OBServer也可以自己获取,跟lscpu里结果一致。但是当需要单机启动多个OBServer进程的时候,可能就需要平分一下物理机的CPU。另外一个用途就是反过来的,当物理机或者虚拟机CPU很少时,故意调大这个参数可以欺骗OBServer进程,以让它能启动(否则CPU少于6个,OBServer可能会启动失败)。
  • memory_limit:指定OS的内存大小。同样不指定的时候,会默认取OS总内存的一定比例。这个比例是另外一个参数memory_limit_percentage控制,默认值是80%。当单机启动多个进程时,还可以通过参数memory_limit平分主机内存。由于进程启动时对内存是独占式的,且会立即分配一定大小的内存,所以这个参数不能欺骗OB,否则运行过程中OBServer会报内存不足而不稳定或者根本就无法启动。
  • datafile_size:指定OBServer启动后数据目录的空间大小。不指定的时候,会默认取数据目录空间的一定比例初始化数据文件。这个比例是另外一个参数data_disk_usage_limit_percentage指定,默认值是90%。另外一种指定数据文件大小的方式是datafile_size。所以,由于空间会预分配,这两个参数(二选一)也不能欺骗OB,否则会启动失败。当单机启动多个OBServer进程时,会需要明确设定这个参数值,以平分存储空间。
  • clog_disk_usage_limit_percentage:指定OBServerclog可用空间占目录比例。通常目录空间使用率100%就是空间满,OBServer为避免写事务日志因为磁盘空间满而出问题,将这一比例降到clog_disk_usage_limit_percentage指定的值。默认值是95%。这样当到达95%OBServer因为写不进clog就出现集群异常,这个时候如果不能清理目录释放空间的话,还可以临时重启OBServer进程指定这个参数更大一些来临时修复问题,此后还是需要尽快对磁盘扩容。当然对空间监控可以避免这个问题。


在启动参数里有个-r参数比较特别,它是指定rootservice_list地址的。实际上这个地址也是集群的一个参数。在集群初始化成功后保存到参数文件中。(有关rootservice可以参考文章《OceanBase数据库实践入门——了解总控服务》。)

不过这样还不是很方便。对于集群初始化时的三个节点,指定这个rootservice_list是有必要的。但对于后续新增的节点,如果每个节点都要取指定这个参数值就不方便,因为这个参数的值还有可能会动态的变化,如果要求运维人员记住这个参数变化后的值这是一个负担。所以OBServerrootservice_list参数变化后将值保存到远端的一个数据库里。不过不是直接写入到那个数据库,而是远端提供了一个API用于响应读取和写入这个参数值。这个API又是通过参数obconfig_url指定的。

所以启动OBServer进程的时候必须指定rootservice_list,这个地址可以手动指定一堆IP,或者指定obconfig_url地址。二选一。obconfig_url描述的API就是由OCP提供的,那个数据库就是OCP的元数据库。这个设计比较特别,详细原因详细的可以查看《自动化运维产品的命门——元数据库》。

SQL审计参数

OceanBase在SQL性能诊断方面有个很有用的功能叫SQL审计视图(gv$sql_audit),可以方便开发运维排查在OceanBase运行过的任意一条SQL,不管这些SQL是成功还是失败,都有详细的运行信息记录。如执行时间、执行节点、执行计划id、会话id、执行时间、等待时间、总时间、排队时间、相关block读取信息、执行报错信息等等。有关详细使用方法请参见《阿里数据库性能诊断的利器——SQL全量日志》。

这个视图的内容都保存在内存的一个FIFO的队列里,内存大小由参数sql_audit_memory_limit控制,默认值3G。还有另外一个参数sql_audit_queue_size控制记录数,默认值是1000万。一个繁忙的数据库,SQL记录数或者这个大小很快就会超过这两个阈值。然后早期的SQL运行数据就没了。所以通常OCP会近实时抽取这个数据。当然如果不想用这个SQL审计功能,还可以关闭它。由参数enable_sql_audit控制,默认值是False

show parameters like '%audit%';

从ORACLE/MySQL到OceanBase:参数或变量_sql_04


资源分配参数

在前文《揭秘OceanBase的弹性伸缩和负载均衡原理》我介绍了OceanBase对资源的管理方法。其中查看集群资源的SQL如下:

select zone,concat(svr_ip,':',svr_port) observer, cpu_total,cpu_assigned,cpu_assigned_percent, round(mem_total/1024/1024/1024) mem_total_gb, round(mem_assigned/1024/1024/1024) mem_assigned_gb, mem_assigned_percent, unit_Num,round(`load`,2) `load`, round(cpu_weight,2) cpu_weight, round(memory_weight,2) mem_weight, leader_count​​from __all_virtual_server_stat​​order by zone,svr_ip​​;

从ORACLE/MySQL到OceanBase:参数或变量_sql_05


这里面CPU是30个,内存mem_total大小是193G是OBServer启动时从主机获取的。OceanBase可以将主机获取的资源乘以一个系数就是总的可分配资源。这个系数是参数resource_hard_limit决定,默认值是100,即百分百。如果把这个参数调整到120,我们可以看到总资源就扩大了。这个只适用于学习环境CPU节点数比较少的时候扩大CPU节点个数,对于内存,资源池分配的时候是按min_memory指定值起步增加,所以可以将min_memory设低一点。在生产环境不要修改这个,否则可能在业务压力上来时遭遇内存不足(欺骗是会露馅的)。

OceanBase在分配资源单元的时候,如果每个Zone有多个节点的时候,它会考虑各个节点的资源利用情况和负载情况,以决策从那哪个节点里分配资源单元。有个参数resource_soft_limit会影响OB在判断一个节点资源利用率是否合适继续分配资源单元。默认值是50(即百分50).这个值最大不能超过参数resource_hard_limit。这个意思是如果有节点资源利用率低于这个比例,那么就是候选节点之一。只要有候选节点,OB就不会首先挑选其他的资源利用率明显高于这个值的节点。如果集群中小租户比较多,这个参数值可以设置的再低一点。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_06

目前OceanBase集群初始化成功时,会保留一定比例内存用于内部跟业务租户有关的运算。比如说更新统计信息等。这个内存比例由参数system_memory_percentage控制,同时系统还保留几个CPU用于内部逻辑,这个由参数system_cpu_quota控制。这两个参数值都可能会随着OB版本变化而变化。

OB可以有很多会话,但是内部执行请求的工作线程(worker)数量是固定的,对于每个租户而言,worker的数量是租户的CPU配额乘以参数workers_per_cpu_quota的值。参数默认值是10。我们并不建议去修改这个参数。在这么多的worker里,为了避免小而快的查询被一些慢查询SQL占住worker而出现等待过多的现象,OB对SQL的请求队列分为两类,其中一类是用于慢查询的。慢查的标准是执行时间超过参数large_query_threshold的值时就被放入到慢查队列里。同时用于执行慢查队列请求的worker数量比例由参数large_query_worker_percentage控制。这两个参数都是可以根据实际场景SQL特点调整的。比如说如果偏OLAP类查询比较多,则调大这个比例;如果是纯粹OLTP类SQL,则调小这个比例。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_07


资源负载均衡相关参数

OB的负载均衡策略比较复杂,并且可能随着版本演进。这里还介绍不了。不过有些确定的逻辑倒是可以提一下。比如说每个租户资源池在每个Zone都有Unit,如果某个租户在该ZoneUnitCPU非常忙,而它其他两个ZoneUnit可能非常空闲(可能大部分是follower副本又不提供服务)。那么OB可以将其他两个ZoneUnitCPU配额匀一部分给到负载最高的ZoneUnit上。注意是同一个租户不同Zone之间在调剂CPU配额。当然调整的粒度也是受参数tenant_cpu_variation_per_server控制的。


从ORACLE/MySQL到OceanBase:参数或变量_sql_08

如下图中,3个Unit的CPU利用率是不一样的。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_09


在决定是否要做负载均衡的时候,节点里各个Unit的总空间会是一个很重要的因素。理想状况下各个节点内空间利用率应该是均衡的,但实际上不可能完全一样。那么对于空间是否均衡就有个衡量标准。比如说某个节点的空间高出平均值多少水平才算不均衡,这个标准就是参数balancer_tolerance_percentage控制,默认值是10(即百分之10)。注意,这只是其中一个因素。触发均衡策略后能否做Unit迁移也看Unit实际大小和其他节点的剩余空间。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_10

当OB判断要做负载均衡时,就会发起以Partition为单位的副本迁移。OB做副本迁移的时候是现在目标位置生成一个新的Follower副本,该Follower副本会先从已有的一个Follower副本拉取数据和后续的Redo。这其中就不可避免的有跨节点请求。OB有一序列参数可以控制这个分区跨节点传输的效率。下面这些参数是控制节点间分区数据传输写入和读出的并发数。并发太低,分区负载均衡进度太慢;并发太高,节点间数据传输流量过大。

show parameters where name in ('data_copy_concurrency', 'server_data_copy_out_concurrency','server_data_copy_in_concurrency');

从ORACLE/MySQL到OceanBase:参数或变量_数据库_11


OB的负载均衡是目前所有分布式数据库里做得最好的,既让应用免于迁移数据,又提供策略供应用干预。不过俗话说没有最好,只有更好。OB的负载均衡策略还有很大提升空间。在OB里可以通过参数enable_rebalance开启和关闭负载均衡机制。

内存的冻结、转储和合并参数

OB的内存其中一大用途就是保存增量数据,简称为增量内存。这部份增量内存就如同一个水池。业务读写就如同进水管,内存已使用比例会逐步上升。按照这个趋势最终会全部用尽。所以OB还有冻结机制。当已使用内存占增量内存的比例超过参数freeze_trigger_percentage时,就会冻结当前内存中的memtable,然后迅速生成新的memtable用于继续读写。随后对于已经冻结的memtable就开始以SSTable格式转储到磁盘上,释放增量内存。这如同一个放水管。

由于OB的写性能非常好,当对OB进行业务压测的时候,如果写入对内存的消耗速度高于转储对内存的释放速度时,增量内存还是会很快耗尽(时间取决于增量内存的大小,默认是租户内存的50%)。加上可转储的次数是有限的(由参数minor_freeze_times控制),所以理论上总是有可能耗尽增量内存的。所以租户的内存大小要考虑业务写入的压力。如果写入压力很大,就要调低冻结触发参数和调高转储次数。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_12


不过,即使初期租户内存评估不到位,后期也可以扩容的。OB的扩容和缩容都是在线进行的,非常方便。除了转储可以释放内存外,OB每天还有固定的一次大合并(merge),这个时候会把增量内存中memtable和基线内存中的sstable直接合并然后以sstable格式写到数据文件里。这个大合并的时间是由参数major_freeze_duty_time设定的,通常设定在业务低峰期。如凌晨。这个大合并运维也可以手动触发。当反复进行大量写测试之前,建议先发起合并释放内存。

下面是这些参数的值和介绍。

从ORACLE/MySQL到OceanBase:参数或变量_默认值_13


集群的参数还有很多,还包括一些以__开头的隐含参数。这里就先介绍到这里。以后在介绍具体功能的时候再继续介绍参数。接下来看看租户变量。

租户变量

租户变量(variable)的设计主要是参考MySQL的。所以目前介绍的主要是MySQL租户的。其中有些变量特性在ORACLE租户里也有。

租户可能需要调整的变量比较少。

变量查看方法

这个跟MySQL的变量查看和修改方法 是一致的。

show global variables like '%timeout%';​​
​​show global variables where variable_name in ('ob_query_timeout','ob_trx_timeout','ob_trx_idle_timeout');​​

租户超时变量设置

上篇文章《从ORACLE/MySQL到OceanBase:数据库超时机制》介绍了租户跟超时有关的一些参数。其中变量 ob_trx_idle_timeout是 2.x某个版本新增的。

从ORACLE/MySQL到OceanBase:参数或变量_默认值_14


租户白名单变量设置

租户变量ob_tcp_invited_nodes可以针对访问来源设置白名单。白名单格式可以是'%',表示允许所有的来源。也可以是一个或多个具体的IP或者子网。如:10.***.0.0/16等。(注意星号不是语法,是我打码)

mysql> set global ob_tcp_invited_nodes='127.1,10.***.0.0/16';

事务相关变量设置

租户变量autocommit可以控制会话默认是否开启事务,默认值为on。通常应用端也会在jdbc里明确设置,不要依赖数据库默认值。以防数据库默认值被修改。

其他

OB新增了很多变量用于影响执行计划。目前对这些变量细节我还不了解,暂时留到以后介绍。

从ORACLE/MySQL到OceanBase:参数或变量_数据库_15

后记

由于OceanBase版本的演进,还会有更多参数开放,也可能有些参数逐步弃用。不管是架构原理,还是参数,还是运维实践,OceanBase都是一个有深度的数据库。

更多后续分享敬请关注公众号:obpilot

从ORACLE/MySQL到OceanBase:参数或变量_sql_16