
最近被一个 PHP 项目搞得有点头大数据库不用 MySQL也不用 Oracle必须用达梦数据库。以前没在生产环境摸过 DM8心里确实没底。从下载安装包开始到 PHP 成功连上达梦数据库整个过程走下来半天左右就通了。这篇不是官方文档的复读是我自己实际走过一遍的笔记包含 Linux 上的安装命令、PHP 侧连接配置以及几个让我浪费了不少时间的坑。适合两类人一类是要在 Linux 上装达梦并手动初始化实例的运维或实施一类是 PHP 开发需要把现有项目从 MySQL 切到达梦、或者新项目要连接达梦数据库。1. 达梦 DM8 是什么PHP 连它为什么要另做准备先说结论达梦数据库是国产关系型数据库DM8 是现在用得比较多的版本。很多人第一反应是“它兼容 Oracle”所以把连接 Oracle 的习惯搬过来就行实际上没那么简单。如果你是从 MySQL 过来的SQL 里写的反引号、auto_increment、limit这些语法在达梦上大概率会报错更贴近 Oracle 的写法是SEQUENCE、ROW_NUM、DUAL这些。所以不只是连接方式要重新准备SQL 习惯也得跟着调整。PHP 项目要连达梦和连 MySQL 最明显的区别是PHP 默认没有达梦驱动mysqli、pdo_mysql都不认识它。你得先想清楚走哪条路连再动手配环境。1.1 达梦的实际应用场景我这次遇到的情况是单位内部系统指定用国产数据库原因不外乎自主可控、部署环境合规、预算有限几个方向。达梦在政府、金融、能源这些行业的存量项目里出现频率很高尤其是一些原来跑在 Oracle 上的老系统做去 O 改造的时候很多会选达梦因为它的 Oracle 兼容性做得好迁移成本相对可控。对 PHP 项目来说达梦并不算特别常见的搭配但不代表不能连。一个典型的场景是后台管理系统或报表系统已经跑在 PHP MySQL 上因为采购要求要把数据库替换成达梦或者新项目明确要求数据库用达梦业务侧继续用 PHP 开发。这两种情况下你要解决的问题都很类似先让 PHP 能建立连接再处理 SQL 兼容性最后处理性能和运维问题。1.2 PHP 侧可选的三条路ODBC、PDO_ODBC、专用驱动我把 PHP 连接达梦的方式梳理了一下实际能用的大概有三条连接方式依赖适用场景ODBC 原生函数unixODBC php-odbc老项目、简单查询代码改动直观PDO_ODBCunixODBC pdo_odbc新项目统一用 PDO 开发达梦专用 PHP 扩展安装包内随附或单独下载追求性能或官方支持按文档装依赖发行版我最推荐的是 PDO_ODBC 加 unixODBC 的组合。原因很实际PDO 是 PHP 社区通用接口以后就算从达梦换回 MySQL 或换到 PostgreSQL代码主结构不用推倒重来ODBC 是达梦官方提供驱动的标准通道兼容性有保障。专用扩展性能理论上更好但有些 PHP 版本和扩展版本匹配比较挑剔装完还得处理编译期问题踩坑成本偏高。所以除非你拿到的安装包已经带了官方扩展包否则先用 ODBC 把项目跑起来是性价比最高的方案。2. Linux 安装前的准备少做一步就要返工安装达梦数据库本身不算复杂但很容易在准备阶段出问题。我在安装时跳过了一些常规检查结果后面初始化实例和连接的时候反复返工。2.1 先确认操作系统、磁盘和内存达梦对 Linux 发行版没有特别苛刻的绑定我这次用的是 CentOS 系的服务器直接跑 DM8 没问题。安装前至少确认三件事系统架构是 x86 还是 ARM下载对应的安装包不要拿错了内存至少预留 2GB 以上给数据库进程别在只有 1GB 的小机器上跑生产/dm8安装目录和数据目录要有足够空间建议数据盘单独挂载日志和数据分开。检查命令不需要多高级几行就够了uname -m free -h df -h / cat /etc/redhat-release还有人容易忽略磁盘校验达梦安装包通常是 zip 包解压后是一个DMInstall.bin文件。我之前遇到过解压到一半磁盘满了文件缺了一半后续执行时报各种奇怪的段错误。建议解压前先确认磁盘剩余空间解压后再用du -sh看看文件大小是否和安装包说明一致。2.2 创建专用用户和安装目录别拿 root 当数据库管理员达梦官方安装建议是创建一个专用系统用户一般是dmdba用户组叫dinstall。这么做不是形式主义数据库进程如果直接跑在 root 下一旦有安全漏洞影响范围直接到系统层面而且达梦的安装脚本和服务脚本对权限判断很敏感用非 root 用户安装后续报错反而少。我使用的准备命令groupadd dinstall useradd -g dinstall -m -d /home/dmdba -s /bin/bash dmdba mkdir -p /dm8/data chown -R dmdba:dinstall /dm8这里有一个细节安装包解压后要给DMInstall.bin加执行权限否则 root 执行会提示“权限不够”。另外建议把安装包放到dmdba有权限的目录下再用su - dmdba或者直接 root 执行安装达梦安装程序本身会引导你创建目录。2.3 License、环境变量和文件限制安装前还要准备达梦的授权文件。如果是从官方渠道拿的安装包通常会附带演示 key 或正式 key 文件。正式部署时不要把试用 key 随便放上去影响的是后面实例的并发限制和一些高级功能。安装过程中会让你输入 key 文件路径找不到的话也能跳过但实例初始化后可能处于“未授权”状态。另外前面创建好dmdba用户后建议把环境变量写进用户配置里省得每次切用户都要手动 exportcat /home/dmdba/.bash_profile EOF export PATH/dm8/bin:\$PATH export LD_LIBRARY_PATH/dm8/bin:\$LD_LIBRARY_PATH EOFLD_LIBRARY_PATH很关键达梦的命令行工具依赖自己目录下的动态库环境变量不设置disql一运行就报找不到.so文件。最后还要把dmdba的ulimit -n调大一点建议至少在 65536 以上避免高并发时“Too many open files”。3. 命令行安装达梦并初始化一个实例服务器没有图形界面一路./DMInstall.bin -i交互式安装。整个过程信息量不大但每一步的选择会影响后面连接和性能我说说我这次选的。3.1 执行安装脚本到底选了些什么安装命令很简单在解压目录下执行./DMInstall.bin -i安装程序会让你选语言、key 文件、时区然后进入组件选择界面。如果没有特殊要求我建议全选组件。数据库软件体积不大少装几个组件省不了多少空间但后面真要用某个工具时再回去补装很麻烦。安装路径我填了/dm8。这里有个容易忽略的点安装路径不要带空格不要放在/root下否则服务脚本和 PHP 扩展开启时都容易碰到权限问题。安装到自定义路径比如/dm8后面处理起来清爽很多。安装结束后终端会提示你要用 root 用户执行一个脚本路径通常在/dm8/script/root/下面。这一步不能跳过它负责把数据库的启动服务注册到系统里还会处理一些目录权限。我当时就是因为没执行这个脚本后面systemctl里根本看不到达梦服务白白折腾了半天。3.2 用 dminit 初始化实例参数影响性能和字符集安装完成只是把软件放到了磁盘上真正的“建库”工作由dminit完成。切换到dmdba用户执行su - dmdba cd /dm8/bin ./dminit PATH/dm8/data DB_NAMEDAMENG INSTANCE_NAMEDMSERVER \ PAGE_SIZE16 EXTENT_SIZE32 CHARSET1 CASE_SENSITIVEY \ PORT_NUM5236参数解释一下PATH数据文件目录初始化后实例文件都在这里DB_NAME数据库名我习惯叫DAMENGINSTANCE_NAME实例名后面注册服务时会用到PAGE_SIZE页大小可选 8、16、32单位 KB。一个 Page 越大单行能容纳的数据量越大但空间浪费也更多。生产环境建议 16KB 起步不要随便选 8KBCHARSET字符集1是 UTF-80是 GB18030。这个参数后期很难改建议统一用 UTF-8CASE_SENSITIVE大小写敏感。达梦默认对标识符大小写敏感如果你是从 MySQL 切过来的表名字段名的大小写习惯可能要变。接入历史系统时要特别留意PORT_NUM数据库端口默认 5236。初始化成功后输出里会显示实例路径、控制文件路径等信息。记下这些路径后面启动服务和排查问题都要用。初始化之后系统会提示SYSDBA的默认密码我强烈建议首次登录后立刻修改不要拿默认密码上生产。3.3 注册服务、启动数据库并用 disql 自检初始化实例后数据库还没有跑起来。达梦提供了服务注册脚本安装目录下能找到类似/dm8/script/root/dm_service_installer.sh的脚本root 用户执行/dm8/script/root/dm_service_installer.sh \ -t dmserver \ -p DMSERVER \ -dm_ini /dm8/data/DAMENG/dm.ini注册成功后服务名一般叫DmServiceDMSERVER。接着启动systemctl start DmServiceDMSERVER systemctl status DmServiceDMSERVER如果 systemd 里看不到服务可能是旧版本使用的 init 脚本方式可以到/etc/init.d/下找对应的服务脚本用/etc/init.d/DmServiceDMSERVER start启动。启动后用端口检查命令看是否监听ss -lntp | grep 5236端口在监听后再用达梦自带命令行工具检查一次连接disql SYSDBA/SYSDBA SQL select name, create_time from v$database;能查出数据库信息说明实例没问题。这一步一定要做因为后面 PHP 连接报错时如果在达梦这一侧已经能通就可以精准定位到 PHP 或 ODBC 配置上。4. PHP 通过 ODBC 驱动连接达梦数据库最省心的一条路数据库装好只是开始真正让 PHP 连上才是重点。我最后采用的是unixODBC PDO_ODBC方案完整流程分四步装扩展、写驱动配置、测试连接、处理报错。4.1 装好 unixODBC 和 PHP 的 ODBC 扩展在 CentOS/RHEL 系统上直接包管理安装别急着编译 PHP。命令如下yum install -y unixODBC unixODBC-devel yum install -y php-odbcunixODBC-devel一定要装php-odbc在编译或安装时依赖它头文件。如果 PHP 是源码编译安装的需要重新编译并加上--with-pdo-odbcunixODBC这种场景我遇过几次建议先在老环境上跑php -m | grep -i odbc确认扩展是否存在。装完扩展后检查php.ini里是否启用了这几项extensionpdo_odbc extensionodbc如果对应扩展.so文件已经放在扩展目录下但没启用手动加一行再重启 PHP-FPMsystemctl restart php-fpm实际上用发行版自带的php-odbc包时/etc/php.d/下一般能自动生成odbc.ini文件重启服务后php -m就能看到PDO_ODBC和ODBC。4.2 配置 odbcinst.ini 和 odbc.ini把驱动位置告诉系统这是最容易出错的一步。达梦安装包本身带了 ODBC 驱动一般放在安装目录的drivers/odbc下。我这边安装目录是/dm8驱动文件路径大致是/dm8/drivers/odbc/libdodbc.so。不同版本文件名可能不一样找一个又快又准的办法find /dm8 -name *odbc*.so找到.so文件后编辑/etc/odbcinst.ini写入[DM8] DescriptionDM8 ODBC Driver Driver/dm8/drivers/odbc/libdodbc.so再编辑/etc/odbc.ini这个是 DSN数据源配置[DM8] DescriptionDM8 Database DriverDM8 Server127.0.0.1 Port5236 DatabaseDAMENG我强烈建议先不要急着写 PHP用命令行工具isql测一下 DSN 是否通了isql DM8 SYSDBA 你的密码 -v如果isql能进入 SQL 提示符并执行查询说明 unixODBC 和达梦驱动都没问题问题只会出在 PHP 侧。我踩过最典型的一个坑是odbcinst.ini里Driver写成了相对路径isql一直报找不到驱动改成绝对路径后立刻通了。4.3 PDO 和原生 odbc_connect 连接示例配置完 DSN 后PHP 连接代码非常简单。PDO 方式?php $dsn odbc:Driver{DM8};Server127.0.0.1;Port5236;DatabaseDAMENG;UIDSYSDBA;PWDyour_password; try { $pdo new PDO($dsn); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt $pdo-query(SELECT SYSDATE FROM DUAL); var_dump($stmt-fetch(PDO::FETCH_ASSOC)); } catch (PDOException $e) { echo 连接失败: . $e-getMessage(); }原生 ODBC 函数方式?php $conn odbc_connect(DM8, SYSDBA, your_password); if (!$conn) { exit(odbc_errormsg()); } $res odbc_exec($conn, SELECT * FROM v$database); while ($row odbc_fetch_array($res)) { print_r($row); } odbc_close($conn);这段代码里用了DUAL表是故意保留的。达梦对 Oracle 兼容性很好查当前时间用SYSDATE FROM DUAL基本不会出问题。如果是新项目可以建一张用户表用INSERT和SELECT各验证一遍看看达梦处理时间类型和自增主键的具体行为。4.4 PHP 连接达梦的常见报错和解法我把这次和之前遇到过的错误整理成了一份速查表按优先级排查报错现场真正原因处理办法Driver not foundodbcinst.ini 驱动路径错误用绝对路径重启 PHP-FPM[unixODBC][Driver Manager]Data source name not foundodbc.ini 里没有对应 DSN检查/etc/odbc.ini文件名和入口invalid connection string attributePHP 连接字符串格式不对检查大括号、分号和UID/PWD是否齐全Connection timeout达梦服务没启动或端口不通先查ss -lntp和数据库状态User Id/Password invalid用户名或密码错误或大小写问题用isql测一次确认密码字符PHP Fatal error: Uncaught PDOException: could not find driverPHP 没有启用 pdo_odbcphp -m查看扩展修改 php.ini这里我想强调一个排查思路遇到连接问题先定“层”。用disql测数据库层用isql测 ODBC 层用 PHP 脚本测应用层。哪一层先通就知道问题在哪一层。不要一上来就在 PHP 代码里反复改连接串效率极低。5. 连上之后最容易踩的坑编码、事务与账号权限数据库连通只是第一步把 PHP 项目真正跑起来又会冒出几个新问题。这几个坑我在实际迁移时都踩过特意拎出来讲。5.1 字符集一定要在初始化时定好不然中文全变问号达梦的字符集在dminit时就已经确定了后期改非常痛苦。如果你的数据库初始化时选的是GB18030而 PHP 项目统一是 UTF-8查询结果里的中文大概率会乱码。乱码表现分两种一种是在终端里正常在 PHP 页面里乱一种是数据库写入时就变成了问号读出来也是问号。处理原则是初始化实例时优先用CHARSET1UTF-8如果库已经建好保持应用层和数据库层字符集一致尽量“入库前统一转 UTF-8”ODBC 连接串里能传字符集参数就传例如CharsetUTF8实在改不了的PHP 侧用iconv或mb_convert_encoding兜底但这种方案不推荐。有一类经典翻车现场是数据库表字段定义的是VARCHAR2PHP 写入的数据在插入前已经把中文转成了 UTF-8但达梦实例字符集是 GB18030导致长度校验直接报错。这种问题不是连接层能解决的只能从建库参数上根治。5.2 事务和 SQL 习惯别按 MySQL 来写达梦支持事务语法上更接近 Oracle。如果你习惯了 MySQL 的INSERT ... ON DUPLICATE KEY UPDATE、AUTO_INCREMENT、反引号包裹字段名到了达梦会很别扭。我建议连接达梦的 PHP 项目统一用标准 SQL 风格主键值用序列或应用生成不要指望AUTO_INCREMENT分页不要用LIMIT offset, count改用达梦支持的SELECT ... LIMIT实际上达梦兼容性在不同版本有差异最稳的是用 Oracle 风格的ROWNUM或窗口函数字符串拼接用||不要用CONCAT一个个嵌套字段名不要加反引号必要时用双引号。事务处理上PDO 的beginTransaction()/commit()/rollBack()是通用的可以继续用。但如果用原生odbc_connect默认自动提交行为可能和 MySQL 不同我习惯在长事务里显式控制odbc_autocommit($conn, false); odbc_exec($conn, UPDATE ...); odbc_commit($conn);这一条在数据一致性要求高的业务里一定要测清楚别等上线后发现部分更新没提交。5.3 应用账号不直接用 SYSDBA权限要收敛很多人在本机测试时图省事直接用SYSDBA连库这在开发环境可以但生产环境最好创建单独的应用账号。SYSDBA的权限太大一旦 PHP 代码被注入数据库的损失不可控。达梦创建用户的语法和 Oracle 接近大概类似CREATE USER app_user IDENTIFIED BY YourStrongPass123;然后按业务需要授权GRANT SELECT, INSERT, UPDATE, DELETE ON owner_name.t_user TO app_user;很多新手管理员喜欢直接执行GRANT DBA TO app_user千万别这么干。做数据库对接时给出的 PHP 配置里至少做到应用账号只能访问业务 Schema不能操作系统表不能修改实例参数。这样即使连接串泄露影响面也小得多。6. 这次安装运维我额外想提醒的几件事最后这部分是我实际操作中觉得“如果早知道就好了”的经验不一定每个项目都用得上但值得记一下。6.1 安装日志和 root 脚本很关键达梦的安装日志、启动日志都很有用。安装目录下一般能找到log目录数据库启动故障时先去看日志不要猜。我遇到过一次dmserver启动后立刻退出报错信息很模糊最后看日志才发现是数据目录权限没给到dmdba用户。另外安装完成时提示执行的那些 root 脚本不是“建议执行”是“必须执行”。脚本会注册服务和调整系统服务权限。跳过这一步后面用systemctl管理数据库会变得非常别扭所以我建议在执行安装前先看一眼安装日志里的 root 脚本路径装完顺手执行掉。6.2 备份和恢复工具要提前演练达梦自带逻辑备份工具名称很像 Oracle 的exp/imp对应的是dexp和dimp。不要等到数据出问题才第一次用。我在项目上线前做了一次演练大致命令如下# 在 dmdba 用户下执行FULLY 表示全库导出 /dexp SYSDBA/你的密码 FILE/bak/dm_backup.dmp LOG/bak/dm_backup.log FULLY恢复时用dimp对应导入。除了逻辑备份达梦还有物理备份工具dmrman适合做一致性备份和增量备份。生产环境建议至少有一套物理备份策略不要只靠导出。6.3 PHP 连接参数里的超时和错误模式别忘了配很多 PHP 连接达梦的失败不是连不上而是连接后等待太久或者错误处理不到位。我给连接代码加了两项配置之后排错效率明显提升$pdo-setAttribute(PDO::ATTR_TIMEOUT, 5); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);ATTR_TIMEOUT能让 PHP 在数据库假死或网络不通时快速失败而不是卡在默认等待上。ERRMODE_EXCEPTION让每个 SQL 错误直接抛异常配合日志记录问题发生后能快速定位到具体 SQL 语句而不是在页面上一片空白。最后留一个我自己的习惯我第一次连接达梦时先用isql验证驱动和 DSN再走 PHP。这样可以很干净地区分是数据库问题、ODBC 问题还是 PHP 配置问题。先把isql DM8 SYSDBA 密码 -v跑通PHP 那边基本就是改几个参数的事。如果照做一遍还卡住优先检查服务状态和odbcinst.ini、odbc.ini这两个文件90% 的坑都在这。