达梦数据库 DM8 大小写敏感配置与 Docker 部署实战

以“我到底是不是大小写敏感、怎么改成不敏感”为主线,梳理一套可直接操作的 DM8 使用笔记。


1. 场景背景

在容器环境下部署达梦数据库 DM8(单机版)时,我们通常会写出类似的命令:

docker run -itd -p 5236:5236   --restart=always --name dm8_test   --privileged=true   -e PAGE_SIZE=16   -e LD_LIBRARY_PATH=/opt/dmdbms/bin   -e EXTENT_SIZE=32   -e BLANK_PAD_MODE=1   -e LOG_SIZE=1024   -e UNICODE_FLAG=1   -e LENGTH_IN_CHAR=1   -e INSTANCE_NAME=dm8_test   -v /data/dm8/data:/opt/dmdbms/data   dm8_single:dm8_20240715_rev232765_x86_rh6_64

一切都启动得很顺利,但在开发和联调阶段,表名 / 字段名 / 字符串条件的大小写问题就开始频繁“背刺”我们:

  • 有时 select * from user 报错,说找不到表;
  • 有时框架生成的 SQL 默认小写,而我们在工具里一直用大写;
  • 有时字符串比较发现 "abc""ABC" 并不相等……

这背后其实都指向同一个核心问题:DM8 的大小写敏感配置(CASE_SENSITIVE)

本文围绕以下几个问题展开:

  1. 我现在这套 DM8 实例到底是不是大小写敏感?
  2. 如果现在是大小写敏感,有没有办法改成不敏感?
  3. 在 Docker 部署场景下,应该如何正确设置大小写敏感?
  4. 不想删库的前提下,有哪些“折中方案”?

2. DM8 的大小写敏感到底管什么?

DM8 里常说的“大小写敏感”,由一个初始化参数控制:CASE_SENSITIVE。它主要影响两类行为:

  1. 数据库对象标识符
    • 表名、字段名、索引名、视图名、用户等。
  2. 字符串比较行为
    • WHERE NAME = 'abc' 是否把 'abc''ABC' 看作相等。

2.1 标识符的基本规则

  • 未加双引号的标识符:会被自动转换为大写

    CREATE TABLE test(id INT);
    -- 等价于
    CREATE TABLE "TEST"("ID" INT);
    
  • 加了双引号的标识符:完全按原始大小写存储和匹配

    CREATE TABLE "test"( "Id" INT );
    

在大小写敏感的库中:

  • SELECT * FROM TESTSELECT * FROM test
    • 如果表是 CREATE TABLE TEST 建的,一般都没问题,因为内部是 "TEST"
    • 如果你曾经使用过乱七八糟的双引号写法,就可能出现“有的 SQL 能查,有的查不到表”的情况。

2.2 字符串比较的差异

DM8 在大小写敏感库中,字符串比较默认区分大小写:

SELECT 'abc' = 'ABC';   -- 结果通常为 0(不相等)

而在大小写不敏感库中:

SELECT 'abc' = 'ABC';   -- 可以认为是相等

这对应用框架非常关键,尤其是:

  • 用户名 / 账号名称的匹配;
  • 代码里写死的字符串常量;
  • ORM 框架生成的 SQL 习惯;
  • 老系统迁移过来之后,原来在其它数据库里“不区分大小写”的查询,在 DM8 里突然查不到数据。

3. 如何确认当前实例是否大小写敏感?

判断一个 DM8 实例是否大小写敏感,是通过查询函数,而不是看 docker 命令。

3.1 连接到 DM8

以 Docker 单机镜像为例,在宿主机执行:

docker exec -it dm8_test bash
disql SYSDBA/SYSDBA001

说明:SYSDBA/SYSDBA001 是默认账号密码,实际按你的配置为准。

3.2 查询 CASE_SENSITIVE 状态

disql> 提示符下执行:

SELECT CASE_SENSITIVE();

或者部分版本的函数名可能为:

SELECT SF_GET_CASE_SENSITIVE_FLAG();

返回值含义:

  • 返回 1大小写敏感
  • 返回 0大小写不敏感

一般情况下,如果你在 docker 启动时 没有显式指定 CASE_SENSITIVE 环境变量,那么大概率是默认的 1(敏感)


4. CASE_SENSITIVE 的关键点:只在“建库那一次”生效

这一步是很多人踩坑的地方。结论先说:

CASE_SENSITIVE 是建库(初始化)参数,数据库一旦创建成功,该属性就不能修改。

表现为:

  1. 第一次启动 DM8 容器时,如果挂载的 data 目录是空的,入口脚本会自动调用 dminit 初始化数据库,这时会读取 CASE_SENSITIVE 环境变量:

    • 设为 0 ⇒ 建一个大小写不敏感库;
    • 设为 1(或不设置,使用默认值)⇒ 建一个大小写敏感库。
  2. 之后再重启容器时,只要 data 目录里已有数据库文件:

    • 不会再次执行 dminit
    • 也就不会再理会 CASE_SENSITIVE 这个环境变量;
    • 即使你后来 docker run 时加上 -e CASE_SENSITIVE=0,也不会改变库的属性。
  3. 官方文档也说明:

    • 可通过 CASE_SENSITIVE()SF_GET_CASE_SENSITIVE_FLAG() 查询;
    • 数据库创建成功后无法修改。

4.1 改环境变量能不能“救回来”?

不能。典型错误操作:

docker run -itd -p 5236:5236   --name dm8_test   ...   -e CASE_SENSITIVE=0   -v /data/dm8/data:/opt/dmdbms/data   dm8_single:dm8_20240715_rev232765_x86_rh6_64

如果 /data/dm8/data 里已经有之前初始化好的库,那:

  • 容器可以启动;
  • 数据库照常工作;
  • 但是仍然是老的大小写敏感属性

所以 不能指望“改个 docker 环境变量+重启”就把库变成不区分大小写


5. 想改成不敏感,有哪些方案?

我们分几种典型需求来分析。

5.1 方案一:数据还不重要,直接重建库(最简单)

适用于:刚试用 DM8,库里数据只是临时测试,不需要保留。

步骤:

  1. 停容器并删除:
docker stop dm8_test
docker rm dm8_test
  1. 清空原有数据目录(慎重):
rm -rf /data/dm8/data/*
  1. 带上 CASE_SENSITIVE=0 重新启动容器(新库):
docker run -itd -p 5236:5236   --restart=always --name dm8_test   --privileged=true   -e PAGE_SIZE=16   -e LD_LIBRARY_PATH=/opt/dmdbms/bin   -e EXTENT_SIZE=32   -e BLANK_PAD_MODE=1   -e LOG_SIZE=1024   -e UNICODE_FLAG=1   -e LENGTH_IN_CHAR=1   -e CASE_SENSITIVE=0 \      # ★ 不区分大小写
  -e INSTANCE_NAME=dm8_test   -v /data/dm8/data:/opt/dmdbms/data   dm8_single:dm8_20240715_rev232765_x86_rh6_64
  1. 重新建库成功后,SELECT CASE_SENSITIVE(); 应该返回 0

优点:

  • 简单粗暴,一步到位;
  • 不会有历史数据遗留问题。

缺点:

  • 原来的数据全部丢弃,只适用于测试环境或数据可抛弃的场景。

5.2 方案二:保留旧库 + 新建一个不敏感新库(推荐)

适用于:

  • 目前这套大小写敏感的库已经在使用,有数据、有业务;
  • 又希望后续逐步迁移到大小写不敏感的环境。

核心思路:

老库不动,新起一个“大小写不敏感”的 DM8 实例,然后通过导出导入的方式迁移数据。

5.2.1 新建一个不敏感 DM8 实例
  1. 创建一个新的数据目录:
mkdir -p /data/dm8/data_cs0
  1. 启动一个新容器(端口换一个,避免冲突):
docker run -itd -p 5237:5236   --restart=always --name dm8_cs0   --privileged=true   -e PAGE_SIZE=16   -e LD_LIBRARY_PATH=/opt/dmdbms/bin   -e EXTENT_SIZE=32   -e BLANK_PAD_MODE=1   -e LOG_SIZE=1024   -e UNICODE_FLAG=1   -e LENGTH_IN_CHAR=1   -e CASE_SENSITIVE=0 \       # ★ 新库不敏感
  -e INSTANCE_NAME=dm8_cs0   -v /data/dm8/data_cs0:/opt/dmdbms/data   dm8_single:dm8_20240715_rev232765_x86_rh6_64

现在你有两套库:

  • dm8_test:原库(大小写敏感),端口 5236,对应 /data/dm8/data
  • dm8_cs0:新库(大小写不敏感),宿主机访问端口 5237,对应 /data/dm8/data_cs0
5.2.2 导出导入数据

根据实际情况选择工具:

  • 使用 DM 自带的 dexp/dimp
  • 使用 DTS 或图形化工具;
  • 或者写脚本从旧库 SELECT,再插入新库。

迁移的一般步骤:

  1. 在旧库上导出目标用户/模式的数据;
  2. 在新库上创建对应用户/表空间;
  3. 在新库上导入数据;
  4. 回归测试:对应用指向新库连接串,观察业务功能是否正常;
  5. 迁移完成后,再考虑是否下线旧库。

优点:

  • ✅ 不破坏旧环境,出现问题还能立即切回;
  • ✅ 可以逐步迁移,不用“一刀切”;
  • ✅ 对生产环境更安全。

缺点:

  • 需要一套导出导入流程,工作量稍大;
  • 应用侧需要切换连接串。

5.3 方案三:不重建库,SQL 层“伪装”成不敏感

如果暂时不想折腾两套实例,或者生产环境短期没法迁移,也可以在 SQL 层做一些折中处理。注意,这不能改变底层的大小写敏感属性,只是减轻部分问题。

5.3.1 对字符串查询使用 UPPER/LOWER

例如,对用户名做不区分大小写的匹配:

SELECT * FROM T_USER
 WHERE UPPER(USERNAME) = UPPER(:name);

优点:快速见效,不需要改库。
缺点:

  • 影响查询性能(索引可能无法走等值匹配);
  • 需要在大量 SQL 中人为维护这个习惯。
5.3.2 规范对象命名:统一使用大写且不加双引号

在大小写敏感库中,统一使用“大写 + 不加双引号”的写法,会好很多:

-- 推荐:
CREATE TABLE USER_INFO (
  ID       INT,
  USERNAME VARCHAR(64)
);

-- 不推荐:
CREATE TABLE "user_info"(
  "Id" INT,
  "UserName" VARCHAR(64)
);

这样做的好处是:

  • 应用中 select * from user_info 这类 SQL,一般都能正常工作(会转为大写匹配);
  • 避免“偶尔加了一次双引号,从此永远要按那个奇怪的大小写写 SQL”这种坑。

6. 实战总结与最佳实践

结合 Docker 部署 DM8 的场景,推荐的实践顺序如下:

  1. 在第一次部署前就想清楚:是否需要大小写不敏感?

    • 如果系统来自 MySQL/Oracle 等且原本就是“不太 care 大小写”的写法,建议一开始就设置 CASE_SENSITIVE=0
  2. 初始化新实例时显式设置 CASE_SENSITIVE

    • 想不敏感 ⇒ CASE_SENSITIVE=0
    • 想敏感 ⇒ CASE_SENSITIVE=1(或默认值)。
  3. 始终把 data 目录挂载到宿主机,避免库被误删

    -v /data/dm8/data:/opt/dmdbms/data
    
  4. 千万不要指望“加环境变量+重启”能改变大小写敏感

    • 环境变量只在“data 目录为空,首次初始化”的时候生效;
    • 数据库一旦创建成功,CASE_SENSITIVE 就不能改。
  5. 需要从敏感切换到不敏感时:优先考虑“新建库+迁移数据”的温和方案

    • 老库继续对外提供服务;
    • 新库逐步导入数据、调试、验证;
    • 等新库验证通过,再切换应用连接串。
  6. 短期内无法迁移时,可在业务层/SQL 层增加大小写兼容逻辑

    • 字符串比较使用 UPPER() / LOWER()
    • 严格规范对象命名规则,统一大写无引号。

7. 简要 FAQ

Q1:我不删容器,只是清空挂载目录,再加 CASE_SENSITIVE=0,行不行?

  • 技术上可以:容器启动时发现 data 目录为空,会重新初始化库,新的库会按 CASE_SENSITIVE=0 设置;
  • 但是本质上等价于“重建库”,原数据全部丢失,和删容器没太大区别。

Q2:我能不能只在同一个容器里,新建第二套库(不敏感),然后改配置让实例用新库?

  • 理论上可以,但需要改容器里的脚本和配置,操作复杂且不符合容器“一次性”的理念;
  • 实际上 新起一个容器+新 data 目录 更干净、可控。

Q3:字符串大小写不敏感,但对象名我还是希望区分大小写,可以吗?

  • 这涉及更细粒度的配置和具体版本特性,通常建议按“整体敏感 / 不敏感”来规划;
  • 若有精细化需求,建议在测试环境充分验证后再上生产。

8. 结语

DM8 在大小写敏感这件事上和很多人习惯的数据库略有不同:

  • 一旦库建好,属性就固定;
  • 想改,只能通过新建实例 + 数据迁移的方式来实现。

好处是:行为非常确定,没有“半路改配置导致各种诡异兼容问题”;
坏处是:如果前期没设计好,后期调整会有点麻烦。

如果你正打算在新的项目里引入 DM8,强烈建议在刚开始就把 CASE_SENSITIVE 设计清楚,免得上线后才发现“原来框架默认是大小写不敏感的写法”,再回头填坑就费劲多了。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐