ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

达梦数据库6001网络通信异常排查全攻略

达梦数据库6001网络通信异常排查全攻略 达梦数据库连不上报6001网络通信异常这可能是DBA和开发同学最不想在凌晨三点看到的消息之一。我遇到过不止一次而且每次的根因都不太一样有的是防火墙悄悄改了策略有的是实例监听线程假死还有一次折腾了半天发现是客户端连接串里的服务名写错了。这篇文章就把我排查6001报错的全套思路和踩坑记录整理出来按“从外到内、从服务端到客户端、从单机到集群”的顺序讲清楚并提供可直接复用的诊断命令和配置建议。1. 6001报错的本质先分清是网络层不通还是数据库层不搭理你6001在达梦数据库的错误码体系里属于网络通信类异常官方描述是“网络通信异常”。它本质上说明客户端发出的连接请求在TCP连接建立或后续通信过程中失败了。但“网络通信异常”这个描述很笼统它可能是指物理网络不通也可能是指端口被防火墙拦截还可能是指服务端的监听线程已经无法处理新连接甚至是连接建立后协议握手阶段被服务端主动断开。遇到6001第一件事不是急着改配置而是先判断这条报错的“出现时机”。我习惯按两种情况区分一种是应用一启动就连不上立刻报6001另一种是系统跑了一段时间后突然开始报6001。前者大概率是配置、防火墙、服务未启动等问题后者则要考虑连接数打满、监听线程异常、连接池里的旧连接失效等运行时问题。判断清楚这个时机能省掉一大半的排查时间。另一个重要分界线是本机连本机和远程连本机排查路径完全不同。如果你是在数据库服务器上执行disql本地连接也报6001那问题基本锁定在服务端自身如果本地能连、远程不能连那重点看网络路由和防火墙。这条分界线决定了你先看哪一类日志、先跑哪一类命令。我在现场排查时第一步永远是做“网络探活三连”# 检查服务端进程是否存活 ps -ef | grep dmserver # 检查监听端口是否存在默认端口5236 netstat -anp | grep 5236 # 从客户端远程探测端口连通性 telnet 数据库服务器IP 5236如果ps能看到dmserver进程netstat能看到端口在监听telnet也能通但连接仍然报6001那问题就不在“网络通不通”这个层面了而是数据库内部状态出了问题。很多新手在这里容易卡住觉得“端口都通了怎么还报网络异常”实际上达梦的监听线程收到TCP连接后还会进一步做身份校验、实例状态检查等动作任一步骤失败都会以6001等通信类错误返回给客户端。2. 服务端排查清单实例进程、端口监听、防火墙和实例状态一个都不能少2.1 dmserver进程存活不等于实例可用用ps -ef | grep dmserver看到进程在很多人的第一反应是“服务没问题”。这个判断不够严谨。dmserver进程活着只能说明守护进程没退出不代表它还能正常接受连接。我遇到过进程在、端口也在但连接还是报6001的案例原因是实例状态变成了MOUNT而不是OPEN或者归档日志目录满了导致系统进入异常状态。建议用以下命令确认实例状态# 进入达梦安装目录的bin下执行 ./disql SYSDBA/密码localhost:5236 SQL SELECT STATUS FROM V$INSTANCE;正常情况下应返回OPEN。如果返回MOUNT说明实例处于恢复或配置状态此时不能正常提供连接服务。如果连disql都登不进去就需要看日志了。2.2 端口监听排查TCP监听端口可能不止一个达梦实例有主端口和通信端口之分。dm.ini里的PORT_NUM参数定义了客户端连接的主端口默认是5236。但在MPP或DSC环境下还会有额外的MAL通信端口编号通常是MAL_INST_PORT等。如果只放通了5236而没放通MAL端口MPP集群内部通信会失败表面现象也可能是连接报6001。查看端口监听情况时不要只看5236netstat -anp | grep -E 5236|dmserver观察所有dmserver进程监听的所有TCP端口。如果发现实例配置了多个端口但实际只有部分端口处于LISTEN状态说明实例的通信组件初始化有问题重启实例通常能解决但重启前最好先看日志确认原因。2.3 防火墙是最常见的“隐形杀手”这是6001报错里占比最高的根因之一尤其在使用了firewalld或iptables的Linux服务器上。很多人检查防火墙时只看了默认zone忽略了还有多个zone在生效。我见过一次案例数据库服务器是双网卡业务流量走内网网卡防火墙规则只放行了外网网卡的5236端口结果内网客户端连接全部报6001。核对防火墙状态的常用命令# 查看防火墙整体状态 systemctl status firewalld firewall-cmd --state # 查看当前放行的端口和服务 firewall-cmd --list-all firewall-cmd --list-ports firewall-cmd --list-services如果需要临时放行达梦端口生产环境建议用永久规则并严格限制来源IPfirewall-cmd --zonepublic --add-port5236/tcp --permanent firewall-cmd --reload这里要提醒一个细节如果数据库服务器同时开启了firewalld和iptables服务两边都需要检查。有些系统上iptables服务独立运行firewalld的规则已经放行但iptables的规则还在DROP这种叠加场景最容易被忽略。2.4 实例内部状态异常导致的“假网络故障”达梦实例对客户端连接的接收是独立监听线程完成的。如果监听线程发生异常端口依然能被TCP连接因为内核协议栈还在但应用层无法完成握手客户端就报6001。这种情况进程在、端口在、防火墙也没拦但连接就是建立不了。怎么判断是监听线程的问题看达梦的日志# 进入达梦日志目录 cd $DM_HOME/log ls -lt dm_*.log ls -lt *.log重点看dm_DMSERVER_日期.log这类实例日志搜索ERROR、WARN级别的记录尤其是连接接受失败、线程池耗尽之类的信息。日志里如果出现了类似“accept connection failed”或者通信线程异常的字样基本可以确定是服务端接收连接的能力出了问题。这类情况处理起来比较直接重启实例。但重启之前先检查一下dm.ini里的最大连接数配置MAX_SESSIONS 100默认值在不同版本上不一样如果业务并发高且连接数经常打满把MAX_SESSIONS调大可以缓解。注意改完要重启实例才生效。3. 客户端侧的两个隐形坑dm_svc.conf配置和服务名解析3.1 dm_svc.conf写错导致连接串漂移达梦的客户端依赖dm_svc.conf这个文件做服务名解析。它类似于Oracle的tnsnames.ora里面会定义逻辑服务名与实际IP、端口、负载均衡策略的映射关系。排查客户端报6001时这个文件是很容易被忽略的重灾区。我见过最典型的错误是开发同学在代码里写的是服务名DM_PROD但dm_svc.conf里定义的却是DM_PROD_TEST导致客户端解析不到服务名回退到默认配置去连结果连到了错误的IP或端口。报错信息可能不是“服务名不存在”而是直接抛了6001网络通信异常。dm_svc.conf在Windows下位于%DM_HOME%\dm_svc.confLinux下位于/etc/dm_svc.conf内容格式大致如下DM_PROD(192.168.1.10:5236,192.168.1.11:5236) DM_PROD_TEST(192.168.1.20:5236) TIME_ZONE(480) LOGIN_ENCRYPT(0)排查时先把客户端连接串和服务名给我对一遍。最简单的验证方式是# 在客户端bin目录下执行看能否通过服务名解析并连接 ./disql SYSDBA/密码DM_PROD如果直接写IP端口能连、写服务名报6001那问题基本就在dm_svc.conf的配置或者文件位置不对。3.2 连接串里的端口和实例实际端口不一致这个问题看似低级但在混用多个达梦环境的团队里非常常见。服务器上同一个IP可能同时运行了多个达梦实例分别监听不同端口。应用连的是5236但DBA新初始化的实例监听在5237。连接失败后查防火墙、查网络都是通的最后一步步追到应用配置文件里才发现端口写错了。这里分享一个快速定位方法用dmrman工具查看实例的实际端口。进入达梦bin目录执行./dmrman CTRLFILE/dm/data/DAMENG/dm.ctl SHOW或者直接用strings查看控制文件里的端口信息。对比应用配置里的端口和实例实际端口不一致就改应用配置。这个属于配置层面的低级错误但在多人协作的环境里特别容易出现。3.3 客户端工具版本和服务端版本不兼容还有一个容易忽视的点disql、DM管理工具、navicat这些客户端的版本和服务端版本如果差距过大也可能在连接握手阶段出现通信异常。达梦不同大版本比如DM8和DM9在通信协议细节上不完全兼容用旧版工具连新版实例有时候连接就会报6001。遇到这种情况我建议尽量使用与服务端同版本或更高版本的客户端工具。特别要注意的是navicat连接达梦时它依赖的达梦客户端组件版本是固定的如果服务端是很新的版本优先去达梦官网下载对应的新版本客户端组件替换本地驱动。另外还有一个容易混淆的问题连续多次使用错误密码登录后账号会被锁定。默认的登录失败次数限制如果比较严格账号锁定的现象不是直接提示“账号锁定”而是表现为连接握手不成功、通信异常。这种情况在达梦的dm.ini中有对应参数LOGIN_FAIL_RETRY_TIMES 3 LOGIN_FAIL_DETECT_INTERVAL 30如果怀疑账号被锁用SYSDBA登录后执行以下语句查看SELECT USERNAME, ACCOUNT_STATUS, LOCK_DATE FROM DBA_USERS WHERE USERNAME用户名;若是LOCKED状态执行ALTER USER 用户名 ACCOUNT UNLOCK;4. 多实例和集群环境下的6001往往不是单纯的“网络”问题4.1 数据守护与DSC环境下容易踩的坑达梦的高可用架构常见两种数据守护DW即主备库和共享存储集群DSC。很多公司上了主备或者DSC之后应用连库的配置没有同步调整导致6001频发。数据守护场景下主备库之间有守护进程和监视器。正常情况下应用连接的是主库IP或守护进程提供的VIP。如果发生了主备切换而应用连接串里的IP仍然指向原来的主库备库在没有配置ALWAYS_OPEN之类的参数时是不能提供写服务的客户端可能直接报6001。这种情况本质上是“主备状态感知”问题不是网络问题。DSC场景更复杂一些。DSC是达梦的共享存储多实例架构类似Oracle RAC多个实例共享同一份数据文件对外提供统一服务。客户端连接DSC时通常走DSC的连接入口如果客户端配置的服务名没有正确关联DSC所有节点的IP和端口或者某个节点的MAL通信有问题就会出现连接时好时坏、时不时报6001的现象。这里补充一点DW和DSC的定位差异在于DW解决的是数据容灾和故障切换DSC解决的是计算能力的横向扩展和高可用。如果你的目标是故障转移用DW如果目标是负载均衡和算力扩展用DSC。两者的连接配置方式完全不同排查6001时的思路也要分开。4.2 连接池里的失效连接看似6001实则是连接池返回了“僵尸连接”应用层使用连接池Druid、HikariCP、C3P0等的时候连接池会缓存一批到数据库的物理连接。如果数据库发生过重启、主备切换、网络闪断连接池里缓存的物理连接其实已经失效了。当应用从连接池拿到这种“僵尸连接”并执行SQL时数据库端已经不存在这个会话了客户端收不到正常响应报错信息就可能表现为6001网络通信异常。这里的关键排查点在于报6001之前数据库是否有过重启或网络抖动如果有那应用侧的连接池需要做两件事配置连接有效性检测。以Druid为例spring: datasource: druid: test-while-idle: true test-on-borrow: false validation-query: SELECT 1 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000test-while-idle开启后连接池会在空闲连接被申请使用前检测连接是否有效把失效连接剔除掉。SELECT 1在达梦上是支持的不需要改成SELECT 1 FROM DUAL达梦兼容Oracle语法但最简单的SELECT 1执行没问题。配置连接异常重试。如果应用框架支持可以设置获取连接失败后的重试次数和间隔避免数据库正在重启时应用一次性把连接池的连接全部申请完、全部失败、全部报6001形成雪崩。4.3 连接数打满导致的“拒绝服务”达梦的MAX_SESSIONS参数如果配置过小或者应用没有正确释放连接连接数打满后新的连接请求会被拒绝。有时候报错是明确的“超出最大会话数”但也有可能被客户端解释为通信异常尤其是在连接建立后立即被服务端断开的情况下。排查方法SELECT COUNT(*) FROM V$SESSIONS; SELECT COUNT(*) FROM V$SESSIONS WHERE STATEACTIVE; SELECT MAX_SESSIONS FROM V$DM_INI WHERE PARA_NAMEMAX_SESSIONS;如果活跃会话数长期接近MAX_SESSIONS就需要优化连接池参数或调整应用逻辑而不是盲目调大数据库的最大连接数。盲目调大只会把压力转移到数据库服务器资源上最终可能变成数据库响应缓慢而不是连接报错。5. 一次真实的6001排障记录从报错到业务恢复的完整过程下面分享一次我在生产环境遇到的6001排障全过程。当时是一个政务类项目用的达梦8操作系统是麒麟V10应用服务器和数据库服务器分属不同网段。那天下午业务方反馈应用登录报错后台日志显示“6001网络通信异常”。我登录数据库服务器检查ps看到dmserver进程在netstat看到5236端口在监听从应用服务器telnet数据库IP 5236也是通的。第一感觉很奇怪网络层都通为什么会报6001进一步用disql从数据库服务器本地连接发现本地连接正常能进能查。这就把范围缩小到了网络链路和应用侧。我先检查了应用服务器上的dm_svc.conf发现服务名配置的IP和端口没问题。再看telnet能通、但达梦连接不上怀疑是不是中间有网络设备对非标准协议的拦截。于是我在应用服务器上用达梦自带的工具做了一次详细的连接测试./disql SYSDBA/密码192.168.1.10:5236竟然也是6001。但用nc测端口是通的telnet也是通的说明TCP三次握手没问题。问题出现在TCP建立之后的应用层握手阶段。我回头去翻达梦服务端日志发现日志里有这么一条[ERROR] session accept failed, ip192.168.1.100, error code-6001而且不止一条每隔几秒就出现一次。这说明服务端收到了TCP连接请求但在建立会话时失败了。根据这个线索我检查了dm.ini里的客户端认证配置发现LOGIN_ENCRYPT和IP访问控制相关参数没异常。又检查了系统资源ulimit -n显示打开文件数是1024而数据库进程的连接数早就超了1000。问题找到了文件句柄限制导致新连接无法建立。把/etc/security/limits.conf里的nofile调大并重启了数据库服务后问题彻底消失。事后复盘这次排障如果我在第一阶段就检查ulimit -n可能五分钟就能解决。但这个系统之前一直运行正常谁也没想到服务器的文件句柄限制会卡得这么死。现在我把这个检查项也加进了标准排查流程。6. 6001故障的常态化防御监控、巡检与连接池参数调优6.1 建立数据库层面的监控清单6001这类问题与其等它发生再排查不如在日常监控里提前发现苗头。我给客户做达梦运维方案时通常会要求至少覆盖以下几项监控监控项检查方式告警阈值建议实例状态SELECT STATUS FROM V$INSTANCE;非OPEN状态立即告警端口监听netstat -anp | grep 5236端口消失立即告警连接数使用率活跃会话数 / MAX_SESSIONS超过80%告警实例日志ERROR扫描dm_DMSERVER_*.log出现ERROR关键字告警服务器文件句柄cat /proc/pid/limits使用率超80%告警磁盘空间df -h使用率超85%告警这里的核心思路是6001是“结果”不是“原因”。它背后的原因往往是资源耗尽、状态异常或网络配置变更。监控要盯着这些上游指标而不是只盯着错误码本身。6.2 连接池参数的精调思路连接池参数的调整其实没有标准答案完全取决于业务特点。对于达梦数据库我的建议是连接池最大连接数不要超过MAX_SESSIONS的70%留出30%给DBA手工连库排查问题。开启空闲连接检测Druid用test-while-idleHikariCP用connection-test-query或validation-query。设置合理的连接超时时间。连接池获取连接的超时不要设置太长建议3到5秒这样数据库故障时应用不会长时间卡住。数据库发生重启或切换后最好能主动刷新连接池。很多框架支持应用启动时初始化连接但如果运行期间数据库重启过连接池里的旧连接依然存在必须靠有效性检测来剔除。6.3 快速诊断脚本一键收集6001相关线索为了方便排查我自己写了一个简单的脚本分享出来。它能把排查6001需要的信息一次性收集齐省去逐条敲命令的时间#!/bin/bash # 达梦数据库6001网络通信异常快速诊断脚本 # 用法在达梦服务器上以dmdba用户执行传入实例端口号 PORT${1:-5236} DM_HOME${DM_HOME:-/opt/dmdbms} LOG_DIR$DM_HOME/log DATA_DIR${DATA_DIR:-/dm/data/DAMENG} echo 1. 实例进程信息 ps -ef | grep dmserver | grep -v grep echo 2. 端口监听信息 netstat -anp | grep $PORT echo 3. 服务器文件句柄限制 DM_PID$(ps -ef | grep dmserver | grep -v grep | awk {print $2} | head -1) cat /proc/$DM_PID/limits | grep -E Max open files|Max processes echo 4. 防火墙状态 systemctl status firewalld --no-pager 2/dev/null | head -3 firewall-cmd --list-all 2/dev/null echo 5. 磁盘空间 df -h | grep -E dm|data|/ echo 6. 最近实例日志错误信息 ls -lt $LOG_DIR/dm_DMSERVER_*.log 2/dev/null | head -3 for f in $(ls -t $LOG_DIR/dm_DMSERVER_*.log 2/dev/null | head -2); do echo --- $f --- grep -E ERROR|WARN|6001 $f | tail -30 done echo 7. 数据库会话与状态 $DM_HOME/bin/disql SYSDBA/密码localhost:$PORT EOF SELECT STATUS FROM V\$INSTANCE; SELECT COUNT(*) AS TOTAL_SESSIONS FROM V\$SESSIONS; SELECT PARA_VALUE AS MAX_SESSIONS FROM V\$DM_INI WHERE PARA_NAMEMAX_SESSIONS; EXIT; EOF echo 8. dm.ini关键参数 grep -E PORT_NUM|MAX_SESSIONS|LOGIN_FAIL_RETRY_TIMES|LOGIN_ENCRYPT $DATA_DIR/dm.ini | grep -v ^#脚本的输出覆盖了进程、端口、资源限制、防火墙、磁盘、日志、会话和参数八大类信息。生产环境执行一次基本能定位绝大多数6001的根因。把密码替换成实际SYSDBA密码即可建议执行完就删除或做权限管理避免密码泄露。个人实际操作中还有个习惯每次排查完6001我都会把根因、排查过程、解决方式记录到运维文档里形成一个“错误码案例库”。下次再遇到同类报错直接按图索骥效率高很多。毕竟6001这个错误码的背后原因太多了单靠记忆很容易漏掉某个不起眼的检查项。
返回列表