用 Python 连达梦,最近刚折腾完,把过程记下来,省得下次重新踩坑。我用的是 dmPython 这个库,达梦官方提供的 Python 驱动,文档嘛...有,但比较简略,很多细节得自己试。
先搞定环境。驱动安装很简单,pip install dmPython 就装上了,依赖库不多,挺干净。
但是光装库还不够,得让程序找得到达梦的动态链接库,这块搞不好后面连接直接报错。
Linux 上需要设两个环境变量:DM_HOME 指向达梦安装目录,然后把 $DM_HOME/bin 加到 LD_LIBRARY_PATH 里。
比如 export DM_HOME=/opt/dmdbms,export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH。Windows 下稍微麻烦点,要把达梦客户端里的 dpi 那些 .dll 文件丢到 Python 能搜到的路径下,或者直接拷贝到 Python 安装目录的 DLLs 里,嫌麻烦就配一下 PATH 环境变量也行。我当时就在这里卡了一阵,明明 pip 装好了,import 就报找不到动态库,环境变量一设立马好。
连接数据库。参数就四个核心的:用户名、密码、服务器地址、端口。默认用户名和密码都是 SYSDBA,服务器写 localhost,端口 5236,这是达梦的默认端口。其他参数像 autoCommit、schema 这些需要再说。
一个最简单的连接代码大概是这样的:
import dmPythondef connect_database():try:conn = dmPython.connect(user='SYSDBA',password='SYSDBA',server='localhost',port=5236)print("连接成功")return connexcept (dmPython.Error, Exception) as err:print(f"连接失败: {err}")return None
连接失败的话,别急着查代码,先去服务器上看看数据库服务启没启动,防火墙有没有放通 5236 端口。这个坑太常见了,很多时候就是服务没开或者被防火墙拦了。
连上之后,建个测试表。我习惯把 DDL 放一个函数里,方便初始化。
建表语句加个 IF NOT EXISTS,免得重复执行报错。表结构简单点,一个 id 主键,一个 name 字段,加个时间戳默认值。
def create_table(conn):try:cursor = conn.cursor()cursor.execute("""CREATE TABLE IF NOT EXISTS test_table (id INT PRIMARY KEY,name VARCHAR(100),create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)""")print("表创建成功")cursor.close()except (dmPython.Error, Exception) as err:print(f"建表失败: {err}")
然后是增删改查一套下来。
业务域名太多难以管理,来此加密支持单张证书绑定高达100个域名。无论是子域名众多的通配符需求,还是跨域名的多域名证书,都能一次性满足。通过统一的后台管理,所有域名的加密状态一目了然,极大地提升了大规模站点集群的管理效率。
我一般把事务控制放在调用侧,这样灵活一点。插入两条数据,更新一条,查一下全表,再删一条,最后手动 commit。如果中途出异常,记得 rollback,不然连接关掉时可能残留未提交事务,dmPython 默认是自动提交为 False 的,这个要注意。
def crud_operations(conn):try:cursor = conn.cursor()# 插入cursor.execute("INSERT INTO test_table(id, name) VALUES(1, '测试数据1')")cursor.execute("INSERT INTO test_table(id, name) VALUES(2, '测试数据2')")# 更新cursor.execute("UPDATE test_table SET name = '更新数据' WHERE id = 2")# 查询cursor.execute("SELECT * FROM test_table")rows = cursor.fetchall()for row in rows:print(f"ID: {row[0]}, Name: {row[1]}, CreateTime: {row[2]}")# 删除cursor.execute("DELETE FROM test_table WHERE id = 1")cursor.close()conn.commit()except (dmPython.Error, Exception) as err:print(f"操作失败: {err}")conn.rollback()
这里查询结果直接按索引取 row[0] 这样,如果字段顺序变了容易乱,生产代码里最好用列名取值,比如用 fetchone 返回字典那种,不过这里演示就先不管了。
最后再说几个实际中碰到的状况。
连不上往往是服务没起或者防火墙拦了,先查这个,别死磕代码。驱动报错就确认环境变量,Linux 下 LD_LIBRARY_PATH 设对了没,Windows 下 dpi 的 DLL 是不是在搜索路径里,import dmPython 无报错才算环境 ok。权限的话,SYSDBA 没问题,如果用自己建的用户,得 grant 一下对应表的权限,否则操作会失败。
基本上这套流程跑通之后,就可以把达梦当个普通的数据库用,无非就是 SQL 语法有些差异,但标准 SQL 都支持,问题不大。
后续可能会写一下连接池的用法,高并发下用得着。