ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Navicat 连接人大金仓:PostgreSQL 通道配置与迁移避坑指南

Navicat 连接人大金仓:PostgreSQL 通道配置与迁移避坑指南

简介:面向数据库开发、运维及数据迁移人员,这份操作文档围绕使用Navicat连接人大金仓展开,重点解决连接配置、库表管理与SQL处理中的常见问题,适合需要快速上手或对照排查的初、中级读者。文档以1个docx文件交付,压缩包约1.62MB,篇幅集中、目录清晰,便于按章节查阅。内容涵盖Navicat的下载安装与新建连接、账号密码配置、连接成功后的对象管理,并延伸到创建数据库、转储SQL文件、复制为插入语句和执行SQL等实用操作;文中还提示排序规则与字符集保持一致、建议使用C字符集以防乱码,并兼顾官方工具选择与账号权限安全。已有1302人学习下载,可作为连接配置、数据迁移与日常维护的速查参考。对迁移库字符集不一致导致乱码、账号权限不足等排错场景也有提醒,便于读者按目录定位问题并形成可复用的操作清单。

1. 装完 Navicat 第一件事:连接类型里根本没有「人大金仓」

新建连接的下拉框翻三遍,MySQL、PostgreSQL、Oracle、SQL Server、SQLite、MariaDB、MongoDB 一字排开,就是找不到要找的那四个字。多数人的第一反应是版本太老、缺插件、得额外装个驱动包,于是去翻各种来路不明的补丁,折腾半天还是握手失败。实际情况是:Navicat 从来没有单独的国产库连接类型,它走的是 PostgreSQL 通道,参数填对了就能连。这一篇把建连参数、字符集选择、SQL 搬运三段讲透,顺带记五个真会翻车的现场。适合刚从 MySQL 迁过来的后端、被自带图形工具劝退的 DBA,以及第一次接手这套库的运维。

2. 选对连接类型:把人大金仓当 PostgreSQL 连的三个前提

2.1 下拉框里没有它,是协议层被复用了

人大金仓在内核上走的是 PostgreSQL 那一套:通信协议、系统表、SQL 方言,甚至连 psql 那套命令行习惯都能对上号。Navicat 的 PostgreSQL 驱动发出去的是标准 startup 报文,服务端认这个报文,握手就成立。所以不必等一个所谓「官方适配版」,直接选 PostgreSQL 类型建连就行。

但这个复用有三个前提,缺一个就卡在「测试连接」那一步红字报错。

第一,网络层要通。默认端口不是 5432,常见是 54321,具体以实例配置为准。很多人按 PostgreSQL 的习惯填 5432,客户端直接 connection refused,回头却怀疑是驱动版本问题,方向一开始就错了。

第二,服务端认证文件要放行。PostgreSQL 系靠 pg_hba.conf 控制「哪个网段、哪个用户、用哪种认证方式」能进来,人大金仓里对应的是 sys_hba.conf。默认往往只放行本机 127.0.0.1,你从办公网连过去必然被拒,报错里会明确写 no entry for host。

第三,认证方式要匹配。服务端可能配了 md5、scram-sha-256 或 trust,客户端驱动太老不认 scram,就会卡在密码阶段反复弹框。这个现象特别有迷惑性:密码明明是对的,就是进不去。

还有一条不算前提但值得说:Navicat 的「其他」类型里也能配 ODBC 数据源连过去,理论上可行。但多套一层驱动就多一个黑匣子,出问题时分不清是驱动、DSN 还是服务端,我一般不这么干。原生 PostgreSQL 通道少一层,日志也好对。

把这四条先排掉,再去调 Navicat 里的具体参数,效率差好几倍。

2.2 建连参数逐项对照

参数不多,但每一项都有坑,直接列表对照。

字段填什么常见错法
连接名自定义,建议带环境和端口,如prod-kb-54321全叫 local,一周后分不清哪个是哪个
主机实例 IP 或域名,示例192.0.2.10填了 127.0.0.1,实际连的是自己机器
端口默认 54321,以show port为准按 PostgreSQL 习惯填 5432
初始数据库test或template1填了不存在的库名,报 database does not exist
用户名初始化时的管理员常见为system用 root,这套库没有 root 这个角色
密码由 DBA 提供从聊天窗口复制时带了尾部空格
编码UTF-8留「自动」,服务端 locale 非 UTF-8 时出乱码
SSL服务端ssl=on才开无脑勾选,握手阶段直接失败

初始数据库这一栏很多人忽略。它决定连接建立后默认落在哪个库,填一个不存在的名字,连接根本建立不起来,跟权限一点关系都没有。用户名system是初始化时的超级用户,生产环境一般会另建业务账号,别拿超级用户跑应用,出事了连审计都查不出来。

编码那一栏在后来的排错里权重最高。Navicat 默认可能选「自动」,客户端就按本地系统编码去解释字节流,Windows 中文环境下很容易变成 GBK,服务端存的是 UTF-8,一来一回中文就成问号。建连时直接锁死 UTF-8,能省掉后面一半的排查时间。

SSL 这一项要看服务端配置。不确定就先不勾,通了再按需加。反过来,服务端强制 SSL 而你关着,握手会直接断,报错信息通常很短,容易误判成网络问题。

2.3 从「测试连接成功」到「看见表」

动手之前先在能通网的机器上探两下,比在图形界面里反复试快得多。

# 探 TCP 可达性:只验证网络层,不代表认证通过 nc -vz 192.0.2.10 54321 # 用自带命令行确认真实端口与版本,比猜靠谱 # -h 主机 -p 端口 -U 用户 -d 数据库 -c 执行单条语句后退出 ksql -h 192.0.2.10 -p 54321 -U system -d test -c "show port;"

nc返回 succeeded 只能说明端口开着,防火墙没拦。真正的认证问题要用ksql才能暴露出来,它和 Navicat 走的是同一套协议,命令行能进、Navicat 进不去,问题基本就锁定在 Navicat 的连接属性上,比如编码、SSL 或者驱动版本。

图形界面的操作路径是这样:

  1. 连接 → PostgreSQL → 按上一节的表逐项填。
  2. 点「测试连接」。这一步失败先看报错原文,是网络、认证还是密码,三种措辞完全不一样。
  3. 成功后「确定」,双击展开连接,找到「模式(schema)」,再展开public,表就在里面。
  4. 右键连接 →「编辑连接」→ 高级,编码选 UTF-8,保持连接间隔设成 60 秒。

第四步的保持连接间隔是给防火墙准备的。中间隔着一层 NAT 或者安全设备时,空闲连接会被静默掐断,Navicat 界面上还显示连着,一执行 SQL 就报连接已关闭。设个心跳能规避掉这类玄学问题。

连上之后别急着建表,先跑三条语句把服务端底细摸清。

-- 版本与兼容模式 select version(); -- 服务端编码:决定数据怎么落盘 show server_encoding; -- 当前会话编码:决定客户端怎么显示 show client_encoding;

version()的输出里如果带 Oracle 兼容字样,说明这个实例开了兼容模式,后面写 SQL 要留意分页语法、空字符串与 NULL 的处理,这些行为跟原生 PostgreSQL 不一样,照搬网上抄来的语句容易出诡异结果。两个 encoding 必须一致,不一致就是乱码的直接来源,先在会话里set client_encoding = 'UTF8';对齐,再谈别的。

还有一个 MySQL 转过来的人最容易懵的点:这套库是一个库下面还有 schema 这一层,表挂在public里。建完库发现左边树是空的,不是没建成,是没展开 schema。Navicat 默认可能只显示库不显示模式,在连接属性里把「显示所有模式」打开就正常了。

3. 字符集与排序规则:C 还是 zh_CN.UTF-8,选错后面全是乱码

3.1 编码管存,排序规则管比,两件事别混

很多资料把乱码归因到「排序规则不一致」,这个说法不够准确,实践中要拆成两个维度看。

编码(encoding)决定字符怎么落盘、怎么在网络上传输。服务端编码、数据库编码、客户端编码三者不一致,才会出现中文变问号、变方块、变成一串\xe4\xbd\xa0的情况。这跟排序规则没关系。

排序规则(collation)决定order by、索引比较、like匹配按什么顺序和规则走。C是按字节比较,中文按 UTF-8 字节序排,既不是拼音序也不是笔画序,order by name出来的结果在业务方眼里就是乱的。zh_CN.UTF-8依赖操作系统的 locale 数据,宿主机或者容器镜像里没装对应 locale,建库语句会直接报错退出。

原文档建议用C,理由是可移植:换机器、换容器、换云环境都不用操心 locale 缺不缺,建库脚本到哪都能跑。代价就是中文排序不符合阅读习惯,得在应用层或者查询里自己处理。这个取舍我认为是对的,尤其是做迁移的时候,目标环境不可控,少一个外部依赖就少一类故障。

还有一种情况是源库已经用zh_CN.UTF-8建好了,数据也在里面。这时候目标库如果为了省事改成C,字符串比较的结果会变,原本能命中的唯一索引可能因为大小写、重音的处理差异报冲突。所以迁移前必须把源库的这两个值原样抄下来,能对齐就对齐,对不齐要评估影响面。

3.2 把当前库的底细查出来

迁移前的第一件事不是导数据,是查清楚源库到底用什么建的。

-- 列出所有库的编码与排序规则,迁移前先对齐这张表 select datname, pg_encoding_to_char(encoding) as encoding, datcollate, datctype from pg_database order by datname;

datcollate管字符串比较和排序,datctype管字符分类,比如upper()、lower()怎么处理,两者一般设成一样的。看到某个库的encoding是UTF8而datcollate是C,这就是最常见的组合,能跑但中文排序不友好。

列级别还可能单独覆盖:

-- 找出被单独指定过排序规则的列,这些是迁移时的重点 select table_name, column_name, collation_name from information_schema.columns where table_schema = 'public' and collation_name is not null;

列级 collation 优先级高于库级。如果源库里有几列被单独设过,建表脚本里会带collate "..."子句,目标库没有对应 collation 就直接建表失败。这种情况在跨环境迁移里不算罕见,提前查出来比导到一半再回头补要省事。

顺手把当前会话的编码也确认一遍,图形客户端和命令行客户端的结果可能不一样:

-- 会话级编码,跟服务端编码不一致就是乱码源头 show client_encoding; -- 临时切到 UTF-8,只影响当前会话 set client_encoding = 'UTF8';

set是会话级的,断开重连就失效。Navicat 里更彻底的做法是在连接属性的编码栏锁死 UTF-8,每次建连自动带上,不用手工敲。

3.3 建库时怎么定,迁移时怎么对齐

建库语句建议手工写,不要用图形界面的下拉框。DDL 落进版本库,参数看得见,别人接手时不用猜当初选了什么。

-- template0 保证从干净模板起,不受 template1 里已有对象影响 create database app_db with encoding = 'UTF8' lc_collate = 'C' lc_ctype = 'C' template = template0;

template0这个参数值得单独说。默认建库继承template1,而template1上可能被人加过扩展、改过配置,导致同一份脚本在不同实例上建出来的库不一样,甚至报 collation 不匹配。指定template0就是强制用一个干净的、只读的模板,结果可预期。

lc_collate和lc_ctype不写会继承模板的默认值,而默认值跟实例初始化时的环境有关。这就是「同一份脚本,测试环境建出来是 C,生产环境建出来是 zh_CN.UTF-8」的根源。写死,别省这两个参数。

如果源库确实是zh_CN.UTF-8,而目标机器上locale -a里没有这一项,别硬建。两条路:一是让运维在宿主机装 locale 包,二是退回C并在业务层处理排序。中文排序的替代写法可以这样绕:

-- C 排序下按拼音序近似排序,仅适用于 GBK 覆盖的常用汉字 select name from t_user order by convert_to(name, 'GBK');

这个写法有边界:生僻字、扩展区汉字在 GBK 里没有映射,转换会报错或者落到替代字符上。真要做严格的中文排序,老老实实在应用层用排序库处理,别在数据库里硬扛。

图形化建库还有一个隐性风险:Navicat 的建库对话框里,字符集和排序规则是下拉框,默认值跟着连接走,手快一点就选错。我的习惯是建库、建表、建索引全部走查询窗口,DDL 统一管理,改起来也方便 diff。建完立刻跑一遍 3.2 里的查询复核,确认落地的就是想要的那套参数。

4. 数据搬运用法:转储 SQL、复制为插入语句、跑脚本

4.1 转储 SQL 文件:产物长什么样,导入前看哪几行

转储是整个迁移流程里用得最多的功能。右键库或者表 →「转储 SQL 文件」→ 选结构和数据,得到一个.sql文本。产物开头通常是这几行:

-- 转储文件头部,导入前必须确认这几项 SET statement_timeout = 0; -- 取消语句超时,大表导入不会被中途杀掉 SET client_encoding = 'UTF8'; -- 客户端编码,跟文件实际编码必须一致 SET standard_conforming_strings = on; -- 反斜杠不再当转义符,影响含 \ 的字符串 SET search_path = public, pg_catalog; -- 不带前缀的表名往哪找

search_path是导入失败的高频原因。转储时表在public下,导入的目标库如果建在别的 schema 里,脚本里所有不带前缀的create table、insert全都会报表不存在,或者更糟——建到了错误的 schema 里,数据看着导进去了,业务查不到。改这一行比重写整个脚本省事得多。

statement_timeout设成 0 是必要的。默认可能只有几十秒,几百万行的表导到一半被服务端掐断,前面全白干,还得先清理半截数据。导入完成后记得在会话里恢复,别把这个设置带到生产连接上。

client_encoding必须跟文件实际编码一致。Navicat 转储默认按连接编码写文件,如果连接当时是「自动」而系统是 GBK,文件就是 GBK,脚本头部却写着 UTF8,导入时中文全乱。转储之前先把连接编码锁成 UTF-8,这一步别省。

转储选项里还有「仅结构」「仅数据」「包含 drop 语句」几个勾。做结构比对时只导结构;做增量同步时只导数据,但要注意目标表必须先存在且字段对得上。带 drop 语句的脚本重复执行会先删表再建,误点一次就是数据没了,生产环境建议不勾。

4.2 复制为插入语句:适合几十行,不适合几十万行

选中若干行 → 右键 →「复制为插入语句」,剪贴板里就得到可以直接执行的 INSERT。

INSERT INTO "public"."t_user" ("id", "name", "created_at") VALUES (1, '张三', '2024-05-01 10:00:00');

双引号包的是标识符,单引号包的是字符串,这个区分在排错时特别重要。建表时如果用了双引号且写成大写,比如"T_USER",那么查询里必须带引号且大小写完全一致,否则标识符被折叠成小写,报「关系不存在」。反过来建表没加引号,实际落地就是小写,查询加不加引号都能命中。这套规则跟 MySQL 在 Windows 上的行为不一样,从 MySQL 转过来的人几乎都要栽一次。

这个功能适合的场景很明确:补几条配置数据、把线上某几行异常记录搬到测试库复现、给同事发一段能直接跑的样例数据。几十行、几百行都没问题。

不适合的场景同样明确:整表搬迁。几十万行生成出来是一个巨大的文本,粘贴进查询窗口能把客户端卡死,执行起来还是一条一条提交,慢得离谱。整表就用转储,或者用copy命令走文件,效率差一个数量级。

还有一个细节:生成的语句里日期是字符串字面量,目标库的日期格式参数如果跟源库不一样,导入会报格式错误。跨库搬运前确认双方的日期输入格式一致,或者统一改成 ISO 格式带完整时分秒。

4.3 查询窗口执行脚本:选中执行、事务、超时

Navicat 的查询窗口有两个执行按钮,行为完全不同。「运行」执行整个编辑器里的所有语句,「运行已选择」只执行选中的部分。大脚本导入时误点前者,等于把几万行一次性怼进去,中途想停都停不下来。

正确的做法是用事务包起来,出错了能整体回退:

begin; -- 这里放导入脚本,出错时执行 rollback 而不是 commit -- insert into ... ; -- update ... ; commit;

事务的代价是锁和日志膨胀。几百万行放在一个事务里,回滚段会撑得很大,磁盘不够直接失败。这种量级要分批提交,比如每五千行一个事务,脚本里手工切分,或者用命令行工具按文件流式导入。

执行前还要确认三件事:目标库选对了没有(查询窗口顶部有库名下拉,选错库执行是常事)、当前连接是不是只读账号、自动提交开没开。第三条最隐蔽,Navicat 默认可能是自动提交,一条delete少写where,点下运行就没了,没有后悔药。生产连接我一般会勾上只读,改数据走单独的连接。

脚本跑完别只看「执行成功」的提示,跑一条count(*)对一下行数,再抽查几条中文数据看看有没有变问号。转储加导入这套流程,出问题往往不是报错,是静默地少了几行或者字符被替换了。

5. 避坑与排查:五类现场,现象、原因、解决

5.1 测试连接报 no entry for host

现象:Navicat 点测试连接,红字提示FATAL: no pg_hba.conf entry for host "192.0.2.10",命令行从服务器本机连却是好的。

原因:服务端的认证配置文件只放行了本机回环地址,没有你所在网段的条目。这是默认安全策略,不是故障。

解决:找 DBA 在 sys_hba.conf 里加一行host all all 192.0.2.0/24 md5,然后 reload 配置。别自己去改生产库的认证文件,改错一行所有人都连不上。临时验证可以用 SSH 隧道从本机转发,但长期方案还是走正规网段放行。

5.2 建表报 permission denied for schema public

现象:用业务账号连上去,create table报permission denied for schema public,但select正常。

原因:较新的 PostgreSQL 兼容版本收紧了publicschema 的默认权限,普通角色不再自动拥有建表权。很多人按老教程操作,以为建了用户就能建表。

解决:让管理员执行grant create on schema public to 业务账号;,或者更规范的做法是给业务单独建一个 schema,把属主设成业务账号,应用连上去默认落到自己的 schema。后者在多人多项目共用一个实例时尤其必要,避免表名打架。

5.3 中文显示成问号或方块

现象:数据导进去了,select出来中文全是???,但用命令行查又是正常的。

原因:客户端编码和服务端编码不一致。Navicat 连接属性里的编码留了「自动」,客户端按本地系统编码解释字节流,显示层就崩了。数据本身可能没坏,只是显示错了。

解决:连接属性里编码锁死 UTF-8,断开重连;查询窗口里补一句set client_encoding = 'UTF8';双重保险。如果确认数据已经写坏(存进去就是问号),那得从源库重导,改显示救不回来。判断方法是对比length(name)和octet_length(name),字节数明显不对就是真坏了。

5.4 导入后插入报主键冲突

现象:转储导入成功,行数也对,但应用一插入就报duplicate key value violates unique constraint。

原因:转储脚本重建了表结构和数据,但自增序列的当前值没有跟着推进。序列还停在初始值 1,而表里已经有 id 到几万的记录,下一次取号必然撞车。

解决:导入完成后手工把序列推到最大值之后,具体语句在下一章给出。这类问题不会在导入时报错,往往上线跑一阵才暴露,属于典型的延迟爆炸。迁移自检清单里必须有一项专门查序列。

5.5 表名大小写导致「关系不存在」

现象:同一个库,Navicat 里能看到表,SQL 里写select * from t_user却报关系不存在,加双引号写"T_USER"就正常。

原因:建表时标识符带了双引号且是大写,实际存储就是大写。不加引号的标识符会被折叠成小写再去匹配,自然找不到。

解决:统一规范,建表一律不加引号、全小写,用下划线分词。已经建成大写的,要么查询时始终带引号(容易漏),要么重命名成小写。迁移场景下更要注意:源库全小写、目标库建表脚本带了引号,导过去就全变成大写,应用代码一行没改却集体报错。

6. 进阶:把连接和迁移固化成一页自检表

连接调通只是开始,真正省时间的是把配置和检查项固化下来,下一次换环境照着走。

Navicat 支持把连接配置导出成文件:右键连接 →「导出连接」,得到一个配置文件,换台机器导入就能用。这里有个安全提醒——导出文件里可能带密码,别顺手丢进代码仓库。我一般的做法是导出后手工把密码字段清掉,只留主机、端口、编码这些非敏感项,团队共用一份模板,密码各自填。连接再配个颜色标记,生产标红、测试标黄,手滑点错库的概率能降一大截。

迁移这块,我整理了一页自检表,每次动手前逐项打勾:

检查项怎么查通过标准
编码与排序规则查pg_database的 encoding、datcollate源库目标库完全一致
schema 归属查information_schema.columns的 table_schema表落在预期 schema,无遗漏
行数比对逐表count(*)源库目标库一致
自增序列对比序列当前值与表内最大 id序列值大于最大 id
大字段完整性抽查 text、bytea 列的长度与源库octet_length一致
客户端编码show client_encodingUTF8

序列那一项单独给条语句,导入完成后跑一遍,别等上线才发现:

-- 把序列推到表内最大 id 之后,false 表示下一个 nextval 直接返回该值 -- coalesce 处理空表,避免 max() 返回 NULL 导致 setval 报错 select setval('public.t_user_id_seq', coalesce((select max(id) from public.t_user), 0) + 1, false);

三个参数分别是序列名、目标值、is_called。第三位传false,表示下一次nextval返回的就是这个目标值本身;传true则返回目标值加一。空表场景下目标值取 1,第一条插入拿到 1,符合预期。序列名别照抄,按实际的<表名>_<列名>_seq去查,查不到就用\d+ 表名看默认值里写的是什么。

那张自检表我压在桌面便签上很久了。早些年做过一次跨库迁移,转储导入一路绿灯,行数对得上,中文也正常,直接通知业务切流量,结果第二天凌晨写入开始报主键冲突,爬起来查序列,发现它停在初始值没动。从那以后我每次迁移都强制走一遍这张表,尤其是序列那一行,宁可多花十分钟,也不想半夜被电话叫醒。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进