概述
dmPython是DM提供的依据Python DB API version 2.0中API使用规定而开发的数据库访问接口。使用API能对DM数据库进行访问。
dmPythonn 接口当前版本号为 2.3,需要对应的DM Server版本为7.0.0.9以上,Python版本为2.6以上。
本次目标任务为获取到服务器与数据库的关键信息后,将结果插入保存数据的数据库中。
库中数据存放规划
IP | 时间 | 内存使用率 | 会话数使用率 |
前置条件
- 本次使用的Windows 11连接达梦数据库
- 已安装python2.6及以上版本(本文使用版本为anaconda虚拟环境3.8)
- 已安装DM8数据库中的驱动包
Windows版本 dmPython安装
dmPython路径一般为DM安装路径下的drivers/python/dmPython/目录中。
进入anaconda虚拟环境下执行:
cd /dm/drivers/python/dmPython/
python setup.py install
此时一般会报
Microsoft Visual C++ 14.0 is required
原因是C++包的缺失
此时需要下载Microsoft Visual C++ 14.0的包
提取码:8scp
成功安装后。
输入pip list 会在里面找到dmPython 2.3.0,说明已经安装成功。
dmPython 的运行需要使用 dpi 动态库,用户应将 dpi 所在目录(一般为 DM 安装目录
中的 bin 目录)加入系统环境变量。
python版本3.8以下
这个是时候执行
import dmPython
将会正常输出结果
python版本3.8及3.8以上
由于python 3.8为了防止出现DLL 劫持之类的安全风险。限制了DLL的加载规则
必须将DLL包导入到文件的路径才能使用DLL。
import sys
sys.path
输出的结果中找到dmpython-2.3-py3.8-win-amd64.egg
将DM安装路径下的drivers\dpi下所有文件复制到对应的目录下。即可正常打开。
使用paramiko登录远程服务器
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.71.50',port='22',username='dmdba',password='123456')
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
print(commandout)
将登录参数从其中剥离出来
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ip=['192.168.71.50','22','dmdba','123456']
ssh.connect(hostname=ip[0],port=ip[1],username=ip[2],password=ip[3])
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
print(commandout)
现在已经可以监控到我们主机的内存,同理只需要将主机的cpu与磁盘繁忙程度放入监控项。即可完成主机的监控。
使用dmPython远程操作数据库
收集信息
可以使用dmPython包进行查询数据库信息与将数据库时间记录。
import dmPython
cursor = dmPython.connect(user='SYSDBA', password='SYSDBA', server='127.0.0.1', port='5236', autoCommit=True).cursor()
cursor.close()#必须加上关闭,否则没执行一次就会多一个无法删除的state为IDLE的会话,当会话数目达到上限值,将无法登录数据库,只能重启实例
构造出了一个cursor,这个时候可以根据cursor进行查询或写入数据库
ACTIVE_SESSIONS_NUM="""
select COUNT(*) from v$sessions where state = 'ACTIVE'
"""
active_sessions_num = cursor.execute(ACTIVE_SESSIONS_NUM).fetchall()#如果之间execute,返回的类型不具有可读性,需要加一个fetchall()转换为list形式。
print(active_seesions_num)
返回值为元组拼接的列表,仅仅取1值时。参数为int型。
如果想要获取具体的执行SQL信息,可以使用函数SF_GET_SESSION_SQL(),查询结果为TEXT大字段,使用python的cursor.execute 接口,输出结果为str类型。DM目前大字段最大支持长度为2G,如果超过长度就会报错。
现在已经能够获取到当前的内存、活跃会话数。本文目标为获取的是会话数比例。
select
round((session_num/max_num*100.00),2)||'%'
from
(select count(*) as session_num from v$sessions),
(SELECT PARA_VALUE AS max_num FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS')
将sql放入代码中即可得到当前的会话使用率
SESSION_RATE="""
select
round((session_num/max_num*100.00),2)||'%'
from
(select count(*) as session_num from v$sessions),
(SELECT PARA_VALUE AS max_num FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS')"""
session_rate=cursor.execute(SESSION_SQL).fetchall()
print(session_rate)
监控数据存储
当数据都能正常获取。需要将数据存放到一个专门的表中进行保存。
这个时候需要插入表。但是如果当表不存在时。执行sql语句将会报错。
由于数据存放库已经不存在,可以选择两种方式
- 通过人工手动执行脚本。 新建表
- 获取到不存在表后,自动执行create table命令
本文采用方法为第二种创建一个表。
IP='127.0.0.1'
date=datetime.datetime.now()
try:
DATA_NOW_MONITOR="""
INSERT INTO DATABASE_MONITOR VALUES ('{}','{}' ,'{}','{}');
""".format(IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
data_now_monitor=cursor.execute(DATA_NOW_MONITOR)
print('当前状态为:',IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
except Exception as e:
error_data=(str(e).split(']')[0].replace('[CODE:',''))
if error_data=='-2106':
DATA_CREATE_SHEET="""
create table DATABASE_MONITOR(IP varchar(20),time datetime, mem varchar(10),sess varchar(10));
"""
data_create_sheet=cursor.execute(DATA_CREATE_SHEET)
print('success create table DATABASE_MONITOR')
else:
print(e)
监控数据库
现在已经能够正常的获取和将数据写入数据库中。
将执行的命令写入函数打包,并在主函数中添加循环。
import paramiko
import datetime
import dmPython as dm
import time
def get_database_info(ip,ssh_port,ssh_user,ssh_passwd,database_port,database_user,database_passwd):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
cursor = dm.connect(user=database_user, password=database_passwd, server=ip, port=database_port, autoCommit=True).cursor()
ssh.connect(hostname=ip,port=ssh_port,username=ssh_user,password=ssh_passwd)
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
ssh.close()
date=datetime.datetime.now()
try:
DATA_NOW_MONITOR="""
INSERT INTO DATABASE_MONITOR VALUES ('{}','{}' ,'{}','{}');
""".format(IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
data_now_monitor=cursor.execute(DATA_NOW_MONITOR)
print('当前状态为:',IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
except Exception as e:
error_data=(str(e).split(']')[0].replace('[CODE:',''))
if error_data=='-2106':
DATA_CREATE_SHEET="""
create table DATABASE_MONITOR(IP varchar(20),time datetime, mem varchar(10),sess varchar(10));
"""
data_create_sheet=cursor.execute(DATA_CREATE_SHEET)
print('success create table DATABASE_MONITOR')
else:
print(e)
if __name__ == '__main__':
while(1):
conf=['192.168.71.50','22','dmdba','123456','5236','SYSDBA','SYSDBA']#可以直接写conf,也可以将conf写成一个conf配置文件,方便拓展
# with open('conf.txt',encoding='utf-8') as log_file:
# for files in log_file:
# files=files.replace('\n','')
# if files != '':
# conf.append(files)
for i in range(0,len(conf)-1,7):
get_database_info(conf[i],conf[i+1],conf[i+2],conf[i+3],conf[i+4],conf[i+5],conf[i+6])
time.sleep(10)#10s查询一次
此时查询已经有结果了
基础的监控功能已经实现。
如果后续有需求,监测的项目可以自行添加。