达梦数据库DM8命令行工具DIsql实战指南:从连接到自动化运维

发布时间:2026/9/17 10:48:12
达梦数据库DM8命令行工具DIsql实战指南:从连接到自动化运维 做数据库国产化替代这几年我接触最多的就是达梦数据库DM8。很多人一开始习惯用DM管理工具这类图形界面但真正到了生产服务器上排查故障、跑批、做自动化运维时命令行才是底线而达梦数据库DM8自带的DIsql命令行工具就是那个绕不开的入口。它和Oracle的SQL*Plus在习惯上非常接近会Oracle命令的人切到DIsql几乎没有成本这也是达梦在兼容性设计上做得比较顺手的地方。这篇文章不打算铺开讲达梦全部功能而是聚焦DIsql的认识和使用从哪里启动、怎么连接、有哪些高频命令、怎么拿它做自动化脚本和数据导出以及我在真实项目里踩过的几个典型坑。无论你是刚开始接触达梦的新手还是准备从Oracle迁移过来的老手都可以在这篇里找到几条能直接落地的路径。1. DIsql是什么它在达梦生态里承担什么角色1.1 别小看这个字符界面的“瘦客户端”DIsql是达梦数据库DM8提供的一个纯字符界面的命令行交互工具它在达梦生态里的定位基本对标Oracle的SQL*Plus。它的核心能力可以概括成三件事执行SQL语句、运行数据库存储过程或脚本、把查询结果或日志输出到文件。除此之外它还能完成一部分数据库管理操作比如在线执行备份、查看系统视图、调整会话参数。刚接触达梦的人往往会低估这类工具的价值原因是图形化工具确实更直观建表、改表、看数据、导数据鼠标点几下就完成了。但实际项目里你会经常遇到这样的场景服务器上只有SSH终端X11没通或者数据库实例崩溃图形工具连不上又或者需要在凌晨两点通过定时任务自动导出业务报表。这些时候DIsql是唯一稳定可靠的入口。我遇到过最典型的例子是帮客户做迁移跳板机上只有一个精简的Linux系统图形界面不可用Windows下的图形化管理工具远程访问也常常因为网络策略卡壳。这时候DIsql就成了我和数据库之间最直接的一条通道。只要网络能通到数据库端口它就能工作不需要任何额外的桌面环境依赖。1.2 哪些场景绕不开DIsql结合我经手的项目这几类场景我认为是必然要用到DIsql的数据库异常时应急处理。图形工具可能因为实例状态异常而无法连接但DIsql只要能登录到操作系统就能用本地认证方式进去看状态。自动化运维和定时跑批。crontab调用DIsql执行脚本几乎是达梦运维里的标配操作图形工具很难做到无人值守。批处理逻辑复用。同一段SQL要在多个环境重复执行用DIsql脚本可以保证执行逻辑一致切换环境只改连接参数。大数据量导出和筛选。在文本终端里把查询结果用spool导成文件配合Linux命令继续加工比图形界面导出几十万行数据更灵活。学习达梦SQL语法。命令行是验证SQL兼容性最快的工具Oracle的SQL能不能直接跑DIsql里一测便知。1.3 DIsql与DM管理工具、DMRMAN的分工很多人容易把DIsql和其他达梦自带工具搞混这里我简单划个边界。工具形态主要用途一句话点评DIsql命令行客户端执行SQL、跑脚本、导出数据、日常管理运维自动化首选DM管理工具Java图形客户端对象浏览、建表、权限管理、SQL开发适合人机交互操作DM数据迁移工具图形工具批量导入导出、异构数据库迁移一次性迁移很方便DMRMAN命令行工具物理备份、恢复、归档管理专注备份恢复领域DM控制台图形/命令行实例启停、参数修改、服务配置偏向实例级管理DM Monitor命令行工具数据守护集群监控看备机状态用需要特别说明的是DIsql并不是万能的。比如在做完整的物理备份恢复时DMRMAN在管理备份集方面更专业做复杂异构迁移时DM数据迁移工具提供图形化映射界面更好用。DIsql擅长的是SQL级操作和脚本自动化它在达梦工具链中承担的是“母体入口”作用你能通过它做很多管理动作但真正深入备份文件内部管理还是需要专业工具配合。2. 从零开始启动DIsql、连接数据库的几种姿势2.1 环境准备与启动路径Linux下安装完DM8后DIsql一般位于安装目录的bin子目录下默认路径可能是/opt/dmdbms/bin/disql也可能是你安装时自定义的目录比如/dm8/bin/disql。实际操作时我建议不要直接依赖系统的PATH而是把环境变量确认好export DM_HOME/opt/dmdbms export PATH$DM_HOME/bin:$PATH export LD_LIBRARY_PATH$DM_HOME/bin:$LD_LIBRARY_PATH这里特别提醒一个新手容易忽略的问题DIsql启动时会加载达梦相关的动态库如果LD_LIBRARY_PATH没配好会直接报类似“加载动态库失败”的错误。所以不管是通过ssh远程使用还是写进定时任务都要先在脚本开头把这三个环境变量设置正确。Windows环境下更简单安装完DM8后在开始菜单里能找到DIsql的快捷方式本质上就是调用安装目录下的disql.exe。Windows的DIsql用法和Linux完全一致下面的命令可以通用。2.2 三种常用登录方式DIsql的连接格式非常直观核心就一个公式用户名/密码IP:端口。DM8实例的默认端口一般初始化为5236不过具体还是要看dm.ini里的PORT_NUM参数。第一种方式一条命令直接连接disql SYSDBA/SYSDBA192.168.1.10:5236这种方式适合快速验证网络通不通、账号能不能登。执行后如果能进入SQL提示符说明连接成功。第二种方式交互式输入账号密码disql 用户名: SYSDBA 密码: ******交互式的好处是不会把密码直接暴露在shell历史记录里安全性更好。缺点是没法在脚本里自动传入密码所以自动化任务一般不用这种方式。第三种方式先启动工具再建立连接disql /nolog SQL conn SYSDBA/SYSDBA192.168.1.10:5236/nolog的意思是只启动工具但不连接数据库之后再通过conn命令手动连。这种模式在自动化脚本里非常有用因为你可以先执行一些set命令完成环境初始化比如设置显示格式、开启回显等然后才真正连接数据库。另外用conn切换连接时不用退出DIsql处理多个库连续检查的效率会高很多。如果是本地环境也可以简写成disql SYSDBA/SYSDBA默认走本地socket连接。但生产环境下我仍然推荐显式写清楚IP和端口避免默认参数不符合预期。2.3 登录后的第一件事确认环境信息成功登录后先别急着写业务SQL我的习惯是先确认四件事当前库名、数据库版本、登录用户、实例状态。SQL select db_name(); SQL select * from v$version; SQL select user; SQL select status from v$instance;db_name()返回当前数据库名字默认初始化时一般叫DAMENG。v$version能看出来DM8的具体版本号和修订批次。select user会返回当前用户名比如SYSDBA。v$instance则能看到实例当前是打开状态还是挂起状态。在实际项目里我曾遇到过登录成功但查看版本时报错的情况原因是客户端工具版本和服务器端不匹配。所以登录后先看版本是一个非常值得养成的习惯它能帮你避开后续很多莫名其妙的兼容性问题。另外登录后第一件事还可以顺手设置显示参数避免查询结果在屏幕上挤成一团SQL set linesize 200 SQL set pagesize 100这样输出的每行能容纳更多字符并且每100行分一次页阅读体验会好很多。3. 高频命令梳理把DIsql用顺手3.1 查看表结构、索引和用户权限查询表结构是DBA和开发最常用的操作。DIsql支持直接用desc命令SQL desc SYSDBA.EMPLOYEE;执行后能看到字段名、字段类型、是否允许为空、默认值等信息。这个命令胜在快但痛点是不能对结果继续做二次加工比如按字段名过滤、导出成Excel等。需要灵活查询时我更推荐直接查数据字典视图SELECT column_name, data_type, data_length FROM user_tab_columns WHERE table_name EMPLOYEE ORDER BY column_id;DIsql支持达梦内建的系统视图包括USER_TAB_COLUMNS、DBA_TABLES、DBA_INDEXES等这套数据字典的命名和Oracle非常像从Oracle迁移过来的用户基本可以沿用原来的查询习惯。查看某个表的索引同样简单SELECT index_name, index_type, table_name FROM user_indexes WHERE table_name EMPLOYEE;很多人忽略的一个细节是用desc查看的是“当前模式下”的对象。如果表不在当前用户模式下需要带模式名例如desc SYSTEM.EMPLOYEE。这个规则在使用DIsql时和Oracle逻辑一致跨模式操作时特别容易踩坑。3.2 执行SQL脚本文件的三种姿势在DIsql里执行外部SQL脚本最常用的命令是和startSQL /home/dmdba/scripts/create_tables.sql SQL start /home/dmdba/scripts/create_tables.sql这两者的作用相同都会读取指定路径的SQL文件并按顺序执行。区别在于后面直接跟文件路径start命令更口语化适合交互时敲命令。第三种姿势是在操作系统shell里直接通过标准输入传给DIsqldisql SYSDBA/SYSDBA127.0.0.1:5236 EOF set pagesize 0 set linesize 200 select count(*) from dba_tables; exit EOF这种方式我用的最多因为它不需要进入DIsql交互界面就能执行SQL非常适合隐藏在shell脚本或crontab里。需要留意的是heredoc里的SQL语句中如果包含$符号会被bash提前解析展开必要时使用v\$instance这样的转义写法。执行脚本时有几个注意事项脚本末尾如果写了exit执行完就会直接退出DIsql这在自动化中很有用但在交互调试时会让你措手不及。脚本中的相对路径是相对于当前操作系统路径不是相对于DIsql安装目录写./scripts/xxx.sql时要注意当前路径。脚本里尽量显式commit尤其是包含DML操作时否则后续异常可能导致事务被隐式回滚。3.3 用spool把查询结果导出到文件在DIsql里导数据核心命令是spool。它可以把查询结果原样输出到指定文件是生成报表和数据落地的常用方法。基本用法SQL spool /tmp/table_list.txt SQL select table_name from user_tables; SQL spool off;执行后/tmp/table_list.txt文件里会包含查询结果。spool off必须执行否则输出会一直累积在文件里。实际导出时几乎总是配合几个set参数一起用set pagesize 0 set linesize 32767 set feedback off set echo off set trimspool on set head on set colsep ,这里解释一下每个参数的作用pagesize 0意思是取消分页结果不会在每页之间插入空行linesize 32767是把行宽拉到最大避免超长字符被换行feedback off去掉“查询出N行”这种提示echo off不显示SQL语句本身trimspool on去除行尾空格生成的文件更干净colsep ,把列和列之间的分隔符设置为逗号方便生成CSV。一个包含全部参数的综合示例SQL spool /tmp/employee_export.csv SQL set pagesize 0 SQL set linesize 32767 SQL set feedback off SQL set echo off SQL set trimspool on SQL set head on SQL set colsep , SQL select emp_id, emp_name, salary from employee; SQL spool off;注意colsep设置的逗号是紧跟在字符后面的不是标准的CSV格式如果你用Excel直接打开可能发现字段里多了空格。这种情况可以在导出后统一用sed去掉分隔符两侧的空格或干脆导出成自定义分隔符再在Python里处理。如果要做严格的CSV格式建议在SQL中使用字符串拼接把每行拼成一个完整的逗号分隔字符串这样更可控。3.4 set命令里这几个参数一定要记DIsql的set参数非常多我不建议背全部但下面这张表里的参数在真实运维中是高频出现的建议牢牢记下来。参数作用示例set linesize设置行宽影响每行最多显示多少字符set linesize 200set pagesize设置每页行数0表示不分页set pagesize 0set feedback是否显示查询返回行数set feedback offset echo执行脚本时是否回显SQL语句set echo onset timing是否显示SQL执行耗时set timing onset serveroutput是否显示存储过程或匿名块的输出set serveroutput onset autocommit是否自动提交事务set autocommit onset define是否启用替代变量set define onset colsep设置列与列之间的分隔符set colsep ,set trimspool输出到文件时是否去除行尾空格set trimspool onset head查询结果是否显示列头set head on其中set timing on是我个人每次连接后都会开的它能很直观地反映SQL的执行耗时排查慢SQL时不用再额外看监控。set serveroutput on也有一个容易踩的坑如果没开这个参数即使存储过程中调用了打印输出语句你在DIsql里也什么都看不到还以为过程没执行。我在帮同事排查问题时就遇到过这种开发说过程跑了但没输出结果只是忘了set serveroutput on。3.5 替代变量和绑定变量让脚本灵活起来DIsql支持替代变量和绑定变量这两个特性让脚本不只是“一次性执行”而是能接受外部输入、循环复用。替代变量就是用符号引用一个定义好的变量SQL define v_table DBA_USERS; SQL select count(*) from v_table;执行时v_table会被替换成DBA_USERS。这种方式适合在脚本里通过参数切换不同表名、不同条件值。用undefine命令可以清除已定义的变量。绑定变量则和PL/SQL深度结合典型用法是SQL variable v_cnt int; SQL exec select count(*) into :v_cnt from user_tables; SQL print v_cnt;这里variable声明一个绑定变量exec执行一段PL/SQL匿名块把值赋值给它print输出变量值。绑定变量的好处是能在同一个会话中多次引用同一个值避免重复执行相同子查询。以我的经验替代变量适合简单场景绑定变量适合复杂一点的运行报表或存储过程调试。两者结合起来用在自动化脚本里能写出很灵活的运维工具比如一个脚本反复执行不同表的数据量统计。4. 实战案例DIsql在自动化运维中的落地4.1 用DIsql做数据库巡检生产环境巡检是DBA的日常功课。用DIsql写巡检脚本不仅能覆盖实例状态、表空间、会话数等关键指标还能把所有结果集中输出到一个文件里方便后续分析。我的巡检脚本一般长这样#!/bin/bash export PATH/opt/dmdbms/bin:$PATH export LD_LIBRARY_PATH/opt/dmdbms/bin:$LD_LIBRARY_PATH DISQL/opt/dmdbms/bin/disql OUTFILE/tmp/db_check_$(date %Y%m%d).log $DISQL SYSDBA/SYSDBA127.0.0.1:5236 EOF $OUTFILE 21 set linesize 200 set pagesize 100 set feedback on set echo on select 当前时间 as item, to_char(sysdate, yyyy-mm-dd hh24:mi:ss) as value from dual; select 实例状态 as item, status from v\$instance; select 数据库版本 as item, banner from v\$version where rownum1; select 当前连接数 as item, count(*) from v\$sessions; select 表空间使用情况 as item, count(*) from dba_tablespaces; exit EOF这里需要注意的重点是v\$instance中的$符号在bash的heredoc中不转义的话会被当作shell变量替换导致传给DIsql的语句不完整。另一个细节是 $OUTFILE 21把DIsql的标准输出和错误输出都重定向到日志文件这样即使SQL执行失败我们也能从日志里看到完整报错。巡检输出示例大致如下当前时间 2024-06-15 10:30:22 实例状态 OPEN 数据库版本 DM Database Server x64 V8.1.2.126 当前连接数 23 表空间使用情况 6这些信息一次性拿到手基本能判断这套数据库是否处于健康状态。如果实例状态不是OPEN或者连接数异常偏高就需要进一步排查了。4.2 巡检脚本升级表空间增长趋势表空间满是最常见的生产事故之一单独巡检只能看到当前使用量看不到增长趋势。我的做法是把表空间占用信息定期导出到历史表里然后在巡检时对比某段时间的增长。核心SQLselect a.tablespace_name, round((sum(a.bytes) - sum(b.bytes)) / 1024 / 1024, 2) as used_mb, round(sum(a.bytes) / 1024 / 1024, 2) as total_mb, round((sum(a.bytes) - sum(b.bytes)) / sum(a.bytes) * 100, 2) as used_pct from dba_data_files a, dba_free_space b where a.tablespace_name b.tablespace_name group by a.tablespace_name;这段SQL从DBA_DATA_FILES和DBA_FREE_SPACE两个视图中汇总每个表空间的总大小、已用空间和使用率。达梦兼容Oracle的数据字典视图所以这段SQL在DM8里可以直接执行。如果某天表空间使用率突然接近90%我会进一步定位到底是哪个表占的空间大select segment_name, segment_type, sum(bytes)/1024/1024 as size_mb from dba_segments where tablespace_name MAIN group by segment_name, segment_type order by size_mb desc;这种“先看趋势再定位对象”的排查思路比盲目扩容靠谱得多。我在实际项目里遇到过多次因为日志表、流水表被无限膨胀导致磁盘告警的情况用上面两句SQL基本5分钟内就能锁定元凶。4.3 用DIsql配合crontab定时导出业务数据定时导出报表是DIsql在自动化运维里最常见的应用场景。比如每天早上8点导出昨天的订单数据然后发给数据分析团队。对应脚本#!/bin/bash export PATH/opt/dmdbms/bin:$PATH export LD_LIBRARY_PATH/opt/dmdbms/bin:$LD_LIBRARY_PATH LOG_DIR/data/dm_report TODAY$(date %Y%m%d) mkdir -p $LOG_DIR disql SYSDBA/SYSDBA127.0.0.1:5236 EOF set pagesize 0 set linesize 32767 set feedback off set echo off set trimspool on set head on set colsep , spool $LOG_DIR/order_report_$TODAY.csv select order_id, customer_name, order_amount, create_time from t_order where trunc(create_time) trunc(sysdate - 1) order by create_time; spool off exit EOF这里用trunc(sysdate - 1)来筛选昨天一整天的数据可以绕过to_char函数导致索引失效的问题。spool文件路径里可以使用shell变量拼出带日期的文件名方便每天生成独立的报表文件。然后把这个脚本写进crontab0 8 * * * /home/dmdba/scripts/export_order.sh /var/log/export_order.log 21这里有一个细节值得注意我特意先mkdir -p $LOG_DIR防止目录不存在时spool失败。听起来很基础但第一次写定时任务时很容易忽略导致导出脚本在晚上静默失败第二天早上才发现。4.4 跑批脚本中的事务控制与性能经验DIsql执行大脚本时事务控制比SQL本身更需要关注。DIsql默认情况下一条DML语句执行完不一定立即提交具体取决于会话的autocommit设置。脚本中出现多个DML语句时如果逻辑上是一个整体建议显式用commit或rollback来控制。我的建议是在批处理脚本中遵循三个原则脚本开头明确设置set autocommit off由自己控制提交节点。每个逻辑单元结束后显式commit避免一个中间步骤失败导致前面的操作全部回滚。如果遇到批处理中途异常可以通过DIsql查询v$sessions确认是否有未提交事务占用锁资源。关于性能DIsql执行大批量数据操作时需要注意回显带来的额外开销。脚本里如果没有特殊需求把feedback off和echo off都打开否则训练日志文件里会塞满“x rows affected”这类信息拖慢整体执行速度。还要留意arraysize参数它控制一次从服务器抓取的记录数默认值通常够用但导出超大结果集时适当调大能减少网络往返。5. 常见问题排查与避坑经验5.1 连接不上数据库从哪里下手DIsql登录报错是遇到最多的问题典型报错有“连接失败”“服务器错误”“初始化日志失败”等。我的排查顺序是固定的第一步确认网络和端口。在DIsql所在机器上执行ping 192.168.1.10 telnet 192.168.1.10 5236如果telnet不通检查防火墙、安全组策略、数据库所在服务器端口是否被占用或者dm.ini里的PORT_NUM是否改过非默认值。第二步确认数据库实例进程和状态ps -ef | grep dmserver如果进程不存在说明实例没起来需要先启动服务。如果存在再通过服务端日志看实例是否处于打开状态。第三步确认账号密码正确。达梦安装时设置的SYSDBA密码默认安装有时候会是SYSDBA但正规生产环境一般都会改成强密码。密码不对时数据库日志里会有明确的认证失败记录。第四步确认连接数是否打满。如果数据库长时间运行连接数可能达到上限。这时需要管理员从其他渠道登录释放连接或者在服务端临时调整会话数上限。5.2 DIsql导出文件中文乱码中文乱码是达梦数据库的经典问题DIsql里尤其常见。造成乱码的原因通常是客户端字符集和数据库服务端字符集不一致。判断思路是如果导出文件在Linux下用cat看是正常的拿到Windows上打开乱码多半是文件编码是UTF-8但Windows编辑器默认用ANSI打开如果导出文件在服务器上直接看就是乱码那就要检查DIsql客户端的NLS配置。常规处理办法export LANGzh_CN.UTF-8 export NLS_LANGSimplified Chinese_China.UTF8这两个环境变量在crontab和shell脚本里最容易漏配。因为定时任务默认继承的LANG可能是C或POSIX导致DIsql按非中文编码处理字符串。在正式跑批之前先在交互式终端里导出一个小文件验证编码能省去很多麻烦。如果数据库本身初始化时用的是GBK而客户端用UTF-8连接乱码就几乎不可避免。这种情况下要么在连接时指定字符集要么考虑用CONVERT函数做转换。生产环境我建议在初始化实例时就确定好字符集策略UTF-8对多语言应用友好GBK则更适合纯中文且历史包袱重的系统。5.3 spool导出结果折行、列对不齐导出CSV时如果发现字段被换行或者列对不齐常见原因有两个一是linesize不够大二是某些字段内容本身包含换行符或特殊字符被spool原样写入了。解决方案是先做两件事set linesize 32767 set trimspool on如果字段内容里包含换行则应该在SQL层就处理掉例如把换行符替换成空格select order_id, replace(replace(remark, chr(13), ), chr(10), ) as remark from t_order;这个场景我之前在做数据迁移接口对接时踩过坑导出文件里几行数据中间莫名多出换行导致下游系统解析失败。排查很久才发现是备注字段里带了\n。以后凡是导出text/csv我都会提前清洗字段里的控制字符。5.4 DIsql退出时事务被回滚exit和quit都能退出DIsql但有个容易忽略的细节退出时如果还有未提交的事务数据库会按回滚处理。也就是说如果你在DIsql里执行了一堆insert没有commit就直接exit数据不会真正落盘。这个机制和Oracle的SQL*Plus行为一致。在自动化脚本里如果忘记在脚本末尾写commit定时任务执行了很多次但数据库里始终查不到新增数据很容易让人误判脚本没有执行。排查方法是查看DIsql日志通常能看到查询执行成功但没有提交。所以我的建议是在每个跑批脚本的结束位置统一加一行commit; exit;如果脚本里有多个业务步骤就要在每个步骤完成后即时commit避免一个步骤卡住影响整批事务。5.5 SQL执行卡住怎么快速定位DIsql执行一条SQL长时间没有返回大概率不是DIsql本身的问题而是数据库端发生了锁等待或大事务阻塞。在另一个会话里登录DIsql执行select s.sess_id, s.user_name, s.status, s.state, s.sql_text from v$sessions s where s.state ! ACTIVE and s.sql_text is not null;通过这个查询能看到正在执行的会话和它当前的SQL文本。如果发现某个会话长时间持有锁就可以考虑通知业务方提交或回滚必要时在确保安全的情况下杀掉会话。命令行工具的一个好处是定位问题时不会“挑环境”只要数据库活着DIsql总是先进得去。这个优势在图形工具连不上时尤其珍贵。最后再分享一点我的个人习惯长时间用下来DIsql给我的最大感受是稳定和克制。它不会给你花哨的界面但所有该做的事都能干净利落地完成。我现在每接手一套新的达梦环境都会先通过在DIsql里跑一条综合查询把库的基本情况摸清楚库名、版本、模式、字符集、表空间数量、归档状态。这比打开图形工具一层层点菜单快得多也能在第一时间发现配置异常。如果你刚开始用DIsql建议不要急着背所有命令先强迫自己一周时间只通过DIsql完成日常查询和导出把desc、set、spool、、exit这几个命令练熟练。当你习惯命令行之后会发现在数据库运维这条路上很多环节都比以前省力。达梦在国产数据库里应用越来越广DIsql作为最基础也最可靠的入口值得每一个数据库从业者认真掌握。