openGauss源码解析(160)

openGauss源码解析:AI技术(7)

4. 数据库交互部分源码解析

首先来看一下数据库需要调整的参数是如何在程序中存储的。数据库的参数可能是布尔型的,如off或on,也可以是整数型的或浮点型的。但是,计算机算法(如强化学习、全局搜索算法等)只能接受数值结果,因此需要数值化。这就需要定义一个名为Knob的类,封装数据库的参数。

class Knob(object):

def __init__(self, name, knob):

# 将整形数值转换为数据库可以接受的字符串型字面量

def to_string(self, val):

# 将字符串型的字面量转换为数值型

def to_numeric(self, val):

当DB_Agent类需要被告知要调节的参数时,通过Knob类将待调优的参数包装起来,并作为该类的一个属性存储在内存中。

DB_Agent类实现了对数据库行为的封装,是X-Tuner与数据库进行交互的唯一接口,该类的代码实现如下:

class DB_Agent:

def __init__(self, host, host_user, host_user_pwd,

db_user, db_user_pwd, db_name, db_port, ssh_port=22):

# 设置语句的执行时间不限

self.set_knob_value("statement_timeout", 0)

# 初始化数据库的特征指标接口

self.metric = openGaussMetric(self)

def check_connection_params(self):

# 检查数据库连接参数是否正确

def set_tuning_knobs(self, knobs):

# 设置调优参数,参数类型为RecommendedKnobs, 该类在knob.py文件中定义

if not isinstance(knobs, RecommendedKnobs):

raise TypeError

self.knobs = knobs

self.ordered_knob_list = self.knobs.names()

def exec_statement(self, sql, timeout=None):

# 在数据库内执行SQL语句,是通过调用gsql命令来实现的

command = "gsql -p {db_port} -U {db_user} -d {db_name} -W {db_user_pwd} -c \"{sql}\";".format(

db_port=self.db_port,

db_user=self.db_user,

db_name=self.db_name,

db_user_pwd=self.db_user_pwd,

sql=sql

)

def is_alive(self):

# 检查数据库是否运行

...

def exec_command_on_host(self, cmd, timeout=None, ignore_status_code=False):

# 在数据库的宿主机上执行shell命令

...

def get_knob_normalized_vector(self):

# 获取待调优参数的结果,并将其进行归一化(映射到0与1之间)。返回结果是一个列表

nv = list()

for name in self.ordered_knob_list:

val = self.get_knob_value(name)

nv.append(self.knobs[name].to_numeric(val))

return nv

def set_knob_normalized_vector(self, nv):

# 与get_knob_normalized_vector()方法对应,参数nv表示normalized_vector,即都是已经映射到0与1之间的、经过数值化的参数值,将这些参数值设置到数据库上

restart = False

for i, val in enumerate(nv):

name = self.ordered_knob_list[i]

knob = self.knobs[name]

self.set_knob_value(name, knob.to_string(val))

restart = True if knob.restart else restart

# 如果这些待设置的参数中有需要重启数据库的,则重启数据库以便使设置后的参数生效

if restart:

self.restart()

def get_knob_value(self, name):

# 单独获取某个参数的值,该参数值是不经标准化的

check_special_character(name)

sql = "SELECT setting FROM pg_settings WHERE name = '{}';".format(name)

_, value = self.exec_statement(sql)

return value

def set_knob_value(self, name, value):

# 单独设置某个参数的值,该参数值是不经标准化的,通过gs_guc命令设置数据库参数值

logging.info("change knob: [%s=%s]", name, value)

try:

self.exec_command_on_host("gs_guc reload -c \"%s=%s\" -D %s" % (name, value, self.data_path))

except ExecutionError as e:

if str(e).find('Success to perform gs_guc!') < 0:

logging.warning(e)

def reset_state(self):

# 重置数据库的状态,例如对 pg_stat_database等系统表进行重置

self.metric.reset()

def set_default_knob(self):

# 设置数据库的参数值为默认值,该默认值通过knob类型指定,即在对应的配置文件中指定的值

restart = False

for knob in self.knobs:

self.set_knob_value(knob.name, knob.default)

restart = True if knob.restart else restart

self.restart()

def restart(self):

# 重启数据库

...

def drop_cache(self):

# 对于openGauss数据库来说,drop cache可以使每次benchmark的跑分更加稳定,但是这需要root权限

# 如果用户需要drop cache,则可以向/etc/sudoers中写入'username ALL=(ALL) NOPASSWD: ALL'

...

posted @ 2024-04-30 11:18  openGauss-bot  阅读(2)  评论(0编辑  收藏  举报