概述

dmPython是DM提供的依据Python DB API version 2.0中API使用规定而开发的数据库访问接口。使用API能对DM数据库进行访问。
dmPythonn 接口当前版本号为 2.3,需要对应的DM Server版本为7.0.0.9以上,Python版本为2.6以上。
本次目标任务为获取到服务器与数据库的关键信息后,将结果插入保存数据的数据库中。

库中数据存放规划

IP

时间

内存使用率

会话数使用率

前置条件

  1. 本次使用的Windows 11连接达梦数据库
  2. 已安装python2.6及以上版本(本文使用版本为anaconda虚拟环境3.8)
  3. 已安装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 连达梦库 python操作达梦数据库_python

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

python 连达梦库 python操作达梦数据库_数据库_02


将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)

python 连达梦库 python操作达梦数据库_数据库_03


将登录参数从其中剥离出来

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)

python 连达梦库 python操作达梦数据库_Python_04


现在已经可以监控到我们主机的内存,同理只需要将主机的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)

python 连达梦库 python操作达梦数据库_python 连达梦库_05


返回值为元组拼接的列表,仅仅取1值时。参数为int型。

python 连达梦库 python操作达梦数据库_python_06

如果想要获取具体的执行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)

python 连达梦库 python操作达梦数据库_DM_07

监控数据存储

当数据都能正常获取。需要将数据存放到一个专门的表中进行保存。

这个时候需要插入表。但是如果当表不存在时。执行sql语句将会报错。

python 连达梦库 python操作达梦数据库_python_08


由于数据存放库已经不存在,可以选择两种方式

  1. 通过人工手动执行脚本。 新建表
  2. 获取到不存在表后,自动执行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查询一次

此时查询已经有结果了

python 连达梦库 python操作达梦数据库_DM_09


基础的监控功能已经实现。

如果后续有需求,监测的项目可以自行添加。