| 项目 | 要求 |
|---|---|
| 操作系统 | VMware Workstation (kylin10) |
| 数据库版本 | DM8 |
| 管理工具 | dminit(命令行初始化工具)、disql(命令行查询工具)、 |
| 磁盘空间 | ≥ 40 GB |
# 确认 DM 安装路径
echo $DM_HOME
/opt/dmdbms
# 确认 dminit 与 disql 可用
# 通用的 dminit 命令模板
$DM_HOME/bin/dminit \
PATH=/dm/data/<实例名> \ # 数据文件存放路径
DB_NAME=<数据库名> \ # 数据库名
INSTANCE_NAME=<实例名> \ # 实例名
PORT_NUM=<端口> \ # 监听端口(不同实例使用不同端口)
PAGE_SIZE=<页大小> \ # 页大小 4/8/16/32
EXTENT_SIZE=16 \ # 簇大小
CHARSET=<字符集编码> \ # 0=GB18030, 1=UTF-8
CASE_SENSITIVE=<Y/N> \ # 大小写敏感
LENGTH_IN_CHAR=1 \ # VARCHAR 长度以字符为单位
BLANK_PAD_MODE=<0/1> \ # 空格填充模式(部分版本支持)
UNICODE_FLAG=<0/1> \ # 0=GB18030, 1=UTF-8(与 CHARSET 等效)
SYSDBA_PWD=<密码> \ # SYSDBA 密码
SYSAUDITOR_PWD=<密码> \ # SYSAUDITOR 密码
验证 4 种 PAGE_SIZE(4K / 8K / 16K / 32K)下:
./dminit path=/dmdata/data PAGE_SIZE=32 EXTENT_SIZE=32 CASE_SENSITIVE=y CHARSET=1 DB_NAME=DMTEST INSTANCE_NAME= PORT_NUM=5236 SYSDBA_PWD=****** SYSAUDITOR_PWD=******
说明:PAGE_SIZE 初始化后不可更改,必须新建实例。
# 实例 1:PAGE_SIZE=4
/opt/dmdbms/bin/dminit PATH=/test/DMpage4k PAGE_SIZE=4 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 DB_NAME=DMTEST4K INSTANCE_NAME=DMTEST4K PORT_NUM=5237 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
# 实例 2:PAGE_SIZE=8
/opt/dmdbms/bin/dminit PATH=/test/DMpage8k PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 DB_NAME=DMTEST8K INSTANCE_NAME=DMTEST8K PORT_NUM=5238 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
# 实例 3:PAGE_SIZE=16(默认值)
/opt/dmdbms/bin/dminit PATH=/test/DMpage16k PAGE_SIZE=16 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 DB_NAME=DMTEST16K INSTANCE_NAME=DMTEST16K PORT_NUM=5239 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
# 实例 4:PAGE_SIZE=32
/opt/dmdbms/bin/dminit PATH=/test/DMpage32k PAGE_SIZE=32 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 DB_NAME=DMTEST32K INSTANCE_NAME=DMTEST32K PORT_NUM=5240 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123. BUFFER=1563 # 加一个限制buffer池大小 否则page_size=32太大会导致系统分配BUFFER时太大导致启动实例失败
#原因 OOM
[root@localhost ~]# dmesg -T | grep -i oom
[四 8 月 6 13:20:02 2026] gmain invoked oom-killer: gfp_mask=0x6200ca (GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
[四 8 月 6 13:20:02 2026] oom_kill_process+0xd1/0x100
[四 8 月 6 13:20:02 2026] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
[四 8 月 6 13:20:02 2026] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1001.slice/session-2.scope,task=dmserver,pid=3414,uid=1001
[四 8 月 6 13:20:02 2026] oom_reaper: reaped process 3414 (dmserver), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
# 注册服务后通过服务启动
#DMTEST4K
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DMpage4k/DMTEST4K/dm.ini -p DMTEST4K
#DMTEST8K
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DMpage8k/DMTEST8K/dm.ini -p DMTEST8K
#DMTEST16K
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DMpage16k/DMTEST16K/dm.ini -p DMTEST16K
#DMTEST32K
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DMpage32k/DMTEST32K/dm.ini -p DMTEST32K
-- 连接到对应实例
-- disql SYSDBA/Sysdba123.@localhost:5237 (4K)
-- disql SYSDBA/Sysdba123.@localhost:5238 (8K)
-- disql SYSDBA/Sysdba123.@localhost:5239 (16K)
-- disql SYSDBA/Sysdba123.@localhost:5240 (32K)
-- 查看页大小
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='GLOBAL_PAGE_SIZE';
-- =====================================================
-- 测试方法:逐步创建更宽的 VARCHAR 表,直到建表失败
public static void main(String[] args) {
Connection conn = null;
try {
// 加载达梦驱动
Class.forName("dm.jdbc.driver.DmDriver");
conn = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功\n");
int low = 1;
int high = 100000; // 搜索上界,足够大
int best = 0;
// 二分查找
while (low <= high) {
int mid = (low + high) / 2;
boolean ok = tryCreateTable(conn, mid);
if (ok) {
best = mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
System.out.println("====================探测结果====================");
System.out.println("当前库VARCHAR最大可定义长度:" + best);
System.out.printf("VARCHAR(%d) 建表成功;VARCHAR(%d) 报-6121数据精度超出范围%n", best, best + 1);
} catch (Exception e) {
e.printStackTrace();
} finally {
close(conn);
}
}
-- 创建 N 个 VARCHAR(100) 的列,测试最大列数
-- 例如 PAGE_SIZE=4 时:
List<Result> results = new ArrayList<>();
for (String[] cfg : DB_CONFIGS) {
String label = cfg[0], url = cfg[1], user = cfg[2], pass = cfg[3];
System.out.println();
System.out.println(repeat('=', 60));
System.out.println(" " + label + " (" + url + ")");
System.out.println(repeat('=', 60));
Result r = new Result();
r.label = label;
try (Connection conn = DriverManager.getConnection(url, user, pass)) {
conn.setAutoCommit(true);
r.pageSize = queryPageSize(conn);
System.out.printf(" 实际 PAGE_SIZE = %d 字节%n%n", r.pageSize);
// ── DDL: 最多多少列 ──
System.out.print(" [DDL] VARCHAR(100) 最多列数: ");
r.maxCols100 = findMaxColumns(conn, DDL_COL_WIDTH);
System.out.printf("%d 列%n", r.maxCols100);
// ── DML: 单列最大数据 ──
System.out.print(" [DML] 1列最大数据字节: ");
r.dmlSingleCol = findMaxRowBytes(conn, 1);
System.out.printf("%d 字节 (利用率 %.1f%%)%n",
r.dmlSingleCol, 100.0 * r.dmlSingleCol / r.pageSize);
// ── DML: 多列最大数据 ──
System.out.printf(" [DML] %d列最大数据字节: ", DML_COL_COUNT);
r.dmlMultiCol = findMaxRowBytes(conn, DML_COL_COUNT);
r.perColOverhead = (r.dmlSingleCol - r.dmlMultiCol) / (DML_COL_COUNT - 1);
r.rowBaseOverhead = r.pageSize - r.dmlSingleCol - r.perColOverhead;
System.out.printf("%d 字节 (每列开销≈%d字节)%n",
r.dmlMultiCol, r.perColOverhead);
-- 记录最大列数
-- DM 中行长度限制与页大小的关系:
-- 理论最大行长 ≈ PAGE_SIZE / 2(但需减去行头开销)
-- 查询每个实例的 VARCHAR 最大长度
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI
WHERE PARA_NAME IN ('GLOBAL_PAGE_SIZE', 'MAX_ROW_SIZE');
-- 在每个实例上创建相同的表并插入相同数据
-- 插入 10000 行数据
-- 查看表占用空间
/*
static void createAndInsert(Connection conn) throws SQLException {
try { execute(conn, "DROP TABLE IF EXISTS " + TEST_TABLE + " CASCADE"); } catch (Exception ignored) {}
execute(conn,
"CREATE TABLE " + TEST_TABLE + " (" +
" ID INT PRIMARY KEY, " +
" C_NAME VARCHAR(50), " +
" C_CODE VARCHAR(20), " +
" C_DESC VARCHAR(200), " +
" AMOUNT DECIMAL(12,2), " +
" QTY INT, " +
" C_DATE DATE, " +
" C_TIME TIMESTAMP, " +
" STATUS CHAR(1), " +
" REMARK VARCHAR(500) " +
")");
String sql = "INSERT INTO " + TEST_TABLE +
" VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
for (int i = 1; i <= ROW_COUNT; i++) {
ps.setInt(1, i);
ps.setString(2, "名称_" + i);
ps.setString(3, "CODE_" + String.format("%06d", i));
ps.setString(4, "描述文本用于占空间测试_" + i + "_存储对比");
ps.setBigDecimal(5, new java.math.BigDecimal(5000 + i % 50000));
ps.setInt(6, i % 1000 + 1);
ps.setDate(7, java.sql.Date.valueOf("2024-01-01"));
ps.setTimestamp(8, new java.sql.Timestamp(System.currentTimeMillis()));
ps.setString(9, i % 3 == 0 ? "A" : (i % 3 == 1 ? "B" : "C"));
ps.setString(10, "备注信息_" + i + "_用于填充字符以测试不同PAGE_SIZE下空间差异");
ps.addBatch();
if (i % 1000 == 0) ps.executeBatch();
}
ps.executeBatch();
}
}
// ==================== 空间查询 ====================
static void queryStorage(Connection conn, StorageResult r) throws SQLException {
// 查询表段大小
try (Statement st = conn.createStatement()) {
// 方式1: USER_SEGMENTS(DBA 权限可用)
ResultSet rs = st.executeQuery(
"SELECT BYTES, BLOCKS FROM USER_SEGMENTS " +
"WHERE SEGMENT_NAME = '" + TEST_TABLE + "' AND SEGMENT_TYPE = 'TABLE'");
if (rs.next()) {
r.tableBytes = rs.getLong("BYTES");
r.blocks = rs.getInt("BLOCKS");
}
rs.close();
// 索引段大小
rs = st.executeQuery(
"SELECT COALESCE(SUM(BYTES), 0) FROM USER_SEGMENTS " +
"WHERE SEGMENT_NAME IN " +
"(SELECT INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME = '" + TEST_TABLE + "')");
if (rs.next()) r.indexBytes = rs.getLong(1);
rs.close();
} catch (SQLException e) {
// USER_SEGMENTS 不可用时,用函数备选
try (Statement st = conn.createStatement()) {
ResultSet rs = st.executeQuery(
"SELECT TABLE_USED_SPACE('SYSDBA', '" + TEST_TABLE + "') AS BYTES, " +
" TABLE_USED_PAGES('SYSDBA', '" + TEST_TABLE + "') AS BLOCKS " +
"FROM DUAL");
if (rs.next()) {
r.tableBytes = rs.getLong("BYTES");
r.blocks = rs.getInt("BLOCKS");
}
rs.close();
rs = st.executeQuery(
"SELECT NVL(INDEX_USED_SPACE(0, 'SYSDBA', '" + TEST_TABLE + "'), 0) FROM DUAL");
if (rs.next()) r.indexBytes = rs.getLong(1);
rs.close();
}
}
r.totalBytes = r.tableBytes + r.indexBytes;
}
*/

| 测试项 | PAGE_SIZE=4K | PAGE_SIZE=8K | PAGE_SIZE=16K | PAGE_SIZE=32K |
|---|---|---|---|---|
| 单列最大 VARCHAR 长度 | 32767字符 | 32767字符 | 32767字符 | 32767字符 |
| 最大列数(VARCHAR(100) x N) | 2048列 | 2048列 | 2048列 | 2048列 |
| 10000 行表占用空间(MB) | 2.25MB | 2.25MB | 2.50MB | 3.00MB |
| 索引最大键长度 | 1024字节 | 2048字节 | 4096 字节 | 8192字节 |
对比 UTF-8 和 GB18030 字符集下:
# 实例 A:UTF-8 字符集
/opt/dmdbms/bin/dminit PATH=/test/DM_utf8 PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 DB_NAME=DMTEST_UTF8 INSTANCE_NAME=DMTEST_UTF8 PORT_NUM=5241 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_utf8/DMTEST_UTF8/dm.ini -p DMTEST_UTF8
# 实例 B:GB18030 字符集
/opt/dmdbms/bin/dminit PATH=/test/DM_gb18030 PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=0 CASE_SENSITIVE=1 DB_NAME=DMTEST_GB18030 INSTANCE_NAME=DMTEST_GB18030 PORT_NUM=5242 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_gb18030/DMTEST_GB18030/dm.ini -p DMTEST_GB18030
-- 连接 UTF-8 实例:disql SYSDBA/Dameng123@localhost:5241
-- 连接 GB18030 实例:disql SYSDBA/Dameng123@localhost:5242
SELECT UNICODE FROM V$DATABASE;
-- 0=GB18030, 1=UTF-8
-- =====================================================
-- 在两个实例上分别执行以下测试
-- 创建测试表
CREATE TABLE T_CHARSET_TEST (
ID INT,
DIGIT_CHAR CHAR(10), -- 纯数字
ENG_CHAR CHAR(10), -- 纯英文
CN_CHAR CHAR(30), -- 纯中文
MIXED_CHAR VARCHAR(100) -- 混合字符
);
-- 插入测试数据
INSERT INTO T_CHARSET_TEST VALUES (
1,
'0123456789', -- 10 个数字
'ABCDEFGHIJ', -- 10 个英文字母
'这是测试字符串', -- 7 个中文字符
'Hello世界123测试ABC' -- 混合字符
);
COMMIT;
-- 使用 LENGTHB 和 LENGTH 函数对比字节 vs 字符
SELECT
ID,
-- 数字字段
DIGIT_CHAR AS DIGIT_VALUE,
LENGTH(DIGIT_CHAR) AS DIGIT_CHAR_LEN, -- 字符长度
LENGTHB(DIGIT_CHAR) AS DIGIT_BYTE_LEN, -- 字节长度
-- 英文字段
ENG_CHAR AS ENG_VALUE,
LENGTH(ENG_CHAR) AS ENG_CHAR_LEN,
LENGTHB(ENG_CHAR) AS ENG_BYTE_LEN,
-- 中文字段
CN_CHAR AS CN_VALUE,
LENGTH(CN_CHAR) AS CN_CHAR_LEN,
LENGTHB(CN_CHAR) AS CN_BYTE_LEN,
-- 混合字段
MIXED_CHAR AS MIXED_VALUE,
LENGTH(MIXED_CHAR) AS MIXED_CHAR_LEN,
LENGTHB(MIXED_CHAR) AS MIXED_BYTE_LEN
FROM T_CHARSET_TEST;


| 字符类型 | UTF-8 每字符字节数 | GB18030 每字符字节数 |
|---|---|---|
| 数字 (0-9) | 1 字节 | 1 字节 |
| 英文 (A-Z, a-z) | 1 字节 | 1 字节 |
| 中文 (汉字) | 3 字节 | 2 字节 |
验证 CASE_SENSITIVE=Y 和 CASE_SENSITIVE=N 两种模式下:
# 实例 A:大小写敏感
/opt/dmdbms/bin/dminit PATH=/test/DM_cs_y PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=y DB_NAME=DMTEST_CSY INSTANCE_NAME=DMTEST_CSY PORT_NUM=5243 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_cs_y/DMTEST_CSY/dm.ini -p DMTEST_CSY
# 实例 B:大小写不敏感
/opt/dmdbms/bin/dminit PATH=/test/DM_cs_n PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=n DB_NAME=DMTEST_CSN INSTANCE_NAME=DMTEST_CSN PORT_NUM=5244 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_cs_n/DMTEST_CSN/dm.ini -p DMTEST_CSN
-- 查看大小写敏感设置
SELECT CASE_SENSITIVE FROM V$DATABASE;

-- =====================================================
-- 在 CASE_SENSITIVE=Y 实例上执行(端口 5243)
-- =====================================================
SELECT CASE_SENSITIVE FROM V$DATABASE;
-- 1. 创建带有大小写的表名
CREATE TABLE "MyTable" (
"MyID" INT PRIMARY KEY,
"MyName" VARCHAR(50)
);
INSERT INTO "MyTable" VALUES (1, 'Alice');
INSERT INTO "MyTable" VALUES (2, 'Bob');
COMMIT;
-- 2. 正确引用(带引号,大小写匹配)
SELECT * FROM "MyTable"; -- ✅ 成功
-- 3. 不带引号(自动转大写 MyTable → MYTABLE)
SELECT * FROM MyTable; -- ❌ 失败(表不存在,因为实际表名是 MyTable)
-- 4. 全大写引用
SELECT * FROM MYTABLE; -- ❌ 失败
-- 5. 查看数据库中实际的对象名
SELECT TABLE_NAME FROM USER_TABLES;
-- 输出:MyTable(注意大小写)

-- =====================================================
-- 在 CASE_SENSITIVE=N 实例上执行(端口 5244)
-- =====================================================
SELECT CASE_SENSITIVE FROM V$DATABASE;
-- 1. 创建表
CREATE TABLE "MyTable" (
"MyID" INT PRIMARY KEY,
"MyName" VARCHAR(50)
);
INSERT INTO "MyTable" VALUES (1, 'Alice');
INSERT INTO "MyTable" VALUES (2, 'Bob');
COMMIT;
-- 2. 查看实际存储的表名
SELECT TABLE_NAME FROM USER_TABLES;
-- 输出:MyTable(保留了原始大小写)
-- 3. 不带引号查询(自动转大写 → MYTABLE)
SELECT * FROM MyTable; -- ✅ 成功!自动匹配到 MyTable
-- 4. 全大写引用
SELECT * FROM MYTABLE; -- ✅ 成功
-- 5. 带引号的小写引用
SELECT * FROM "mytable"; -- ✅ 成功
-- 6. 带引号的正确大小写引用
SELECT * FROM "MyTable"; -- ✅ 成功
SELECT * FROM "MYTABLE"; -- ✅ 成功

-- CASE_SENSITIVE=Y 实例
SELECT CASE_SENSITIVE FROM V$DATABASE;
-- 创建表,列名混合大小写
CREATE TABLE T_COL_CASE (
"EmpID" INT,
"FirstName" VARCHAR(50),
"LastName" VARCHAR(50)
);
-- 查询时必须加引号且大小写匹配
SELECT "EmpID", "FirstName" FROM T_COL_CASE; -- ✅ 成功
SELECT EmpID, FirstName FROM T_COL_CASE; -- ❌ 失败(自动大写为 EMPID)
SELECT "empid", "firstname" FROM T_COL_CASE; -- ❌ 失败
-- CASE_SENSITIVE=N 实例
SELECT CASE_SENSITIVE FROM V$DATABASE;
-- 同样创建表
CREATE TABLE T_COL_CASE (
"EmpID" INT,
"FirstName" VARCHAR(50),
"LastName" VARCHAR(50)
);
-- 不带引号时全部可以(自动转大写后匹配)
SELECT EmpID, FirstName FROM T_COL_CASE; -- ✅ 成功
SELECT EMPID, FIRSTNAME FROM T_COL_CASE; -- ✅ 成功

-- =====================================================
-- 核心测试:CASE_SENSITIVE 参数只影响对象名,不影响数据!
-- 数据比较由 NLS_COMP/NLS_SORT 或 COLLATE 子句控制
-- =====================================================
-- 在两个实例上分别执行
SELECT CASE_SENSITIVE FROM V$DATABASE;
CREATE TABLE T_DATA_CASE (
ID INT PRIMARY KEY,
NAME VARCHAR(50)
);
INSERT INTO T_DATA_CASE VALUES (1, 'Alice');
INSERT INTO T_DATA_CASE VALUES (2, 'alice');
INSERT INTO T_DATA_CASE VALUES (3, 'ALICE');
COMMIT;
-- 在 CASE_SENSITIVE=Y 实例上执行(端口 5243)
SELECT * FROM T_DATA_CASE WHERE NAME = 'Alice'; -- 返回 ID=1
SELECT * FROM T_DATA_CASE WHERE NAME = 'alice'; -- 返回 ID=2
SELECT * FROM T_DATA_CASE WHERE NAME = 'ALICE'; -- 返回 ID=3
-- 在 CASE_SENSITIVE=N 实例上执行(端口 5244)
-- 精确查询(等值匹配)
SELECT * FROM T_DATA_CASE WHERE NAME = 'Alice'; -- 返回 ID=1,2,3
SELECT * FROM T_DATA_CASE WHERE NAME = 'alice'; -- 返回 ID=1,2,3
SELECT * FROM T_DATA_CASE WHERE NAME = 'ALICE'; -- 返回 ID=1,2,3
-- ⚠️ 两种情况结果不相同,在实例端口为5243中,对于大小写是敏感的,在通过数据值查询时也对数据值敏感;但是在实例端口为5244中,其对于大小写不敏感,通过数据值查询的时候也不对数据值敏感
-- 如需大小写不敏感的数据比较,使用函数
SELECT * FROM T_DATA_CASE WHERE UPPER(NAME) = 'ALICE'; -- 返回 ID=1,2,3

| 场景 | CASE_SENSITIVE=Y | CASE_SENSITIVE=N |
|---|---|---|
| 不带引号建表 | 名称转大写存储 | 名称转大写存储 |
| 带引号建表 “Tbl” | 保留原始大小写 “Tbl” | 保留原始大小写 “Tbl” |
| 不带引号查表 MyTable | 查找 MYTABLE(失败) | 查找 MYTABLE,自动匹配 MyTable(成功) |
| 带引号查表 “MyTable” | 精确匹配 “MyTable”(成功) | 精确匹配 “MyTable”(成功) |
| 数据值比较 | 大小写敏感 | 大小写不敏感 |
| Oracle 兼容性 | 推荐 Y | — |
| MySQL 兼容性 | — | 推荐 N |
验证 BLANK_PAD_MODE=0(NO_PAD)和 BLANK_PAD_MODE=1(PAD)两种模式下:
注意:BLANK_PAD_MODE 在 DM9 版本中不可通过
sp_set_para_value动态修改。
# 实例 A:BLANK_PAD_MODE=1(PAD,忽略尾部空格)
/opt/dmdbms/bin/dminit PATH=/test/DM_pad1 PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 BLANK_PAD_MODE=1 DB_NAME=DMTEST_PAD1 INSTANCE_NAME=DMTEST_PAD1 PORT_NUM=5245 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_pad1/DMTEST_PAD1/dm.ini -p DMTEST_PAD1
# 实例 B:BLANK_PAD_MODE=0(NO_PAD,不忽略尾部空格)
/opt/dmdbms/bin/dminit PATH=/test/DM_pad0 PAGE_SIZE=8 EXTENT_SIZE=32 CHARSET=1 CASE_SENSITIVE=1 BLANK_PAD_MODE=0 DB_NAME=DMTEST_PAD0 INSTANCE_NAME=DMTEST_PAD0 PORT_NUM=5246 SYSDBA_PWD=Sysdba123. SYSAUDITOR_PWD=Sysauditor123.
/opt/dmdbms/script/root/dm_service_installer.sh -t dmserver -dm_ini /test/DM_pad0/DMTEST_PAD0/dm.ini -p DMTEST_PAD0
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
-- =====================================================
-- 在 BLANK_PAD_MODE=1 实例上执行(端口 5245)
-- =====================================================
CREATE TABLE T_PAD_EQUAL (ID INT, NAME VARCHAR(20));
INSERT INTO T_PAD_EQUAL VALUES (1, 'ABC');
INSERT INTO T_PAD_EQUAL VALUES (2, 'ABC ');
INSERT INTO T_PAD_EQUAL VALUES (3, 'ABC ');
COMMIT;
-- 等值查询
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC'; -- 返回 ID=1
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC '; -- 返回 ID=2
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC '; -- 返回 ID=3
-- 使用 TRIM 后查询
SELECT * FROM T_PAD_EQUAL WHERE TRIM(NAME) = 'ABC'; -- 返回 ID=1,2,3
-- =====================================================
-- 在 BLANK_PAD_MODE=0 实例上执行(端口 5246)
-- =====================================================
CREATE TABLE T_PAD_EQUAL (ID INT, NAME VARCHAR(20));
INSERT INTO T_PAD_EQUAL VALUES (1, 'ABC');
INSERT INTO T_PAD_EQUAL VALUES (2, 'ABC ');
INSERT INTO T_PAD_EQUAL VALUES (3, 'ABC ');
COMMIT;
-- 等值查询
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC'; -- 返回 ID=1,2,3
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC '; -- 返回 ID=1,2,3
SELECT * FROM T_PAD_EQUAL WHERE NAME = 'ABC '; -- 返回 ID=1,2,3

-- =====================================================
-- BLANK_PAD_MODE=1 实例
-- =====================================================
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
CREATE TABLE T_PK_PAD1 (
ID INT PRIMARY KEY,
CODE VARCHAR(10) UNIQUE
);
INSERT INTO T_PK_PAD1 VALUES (1, 'ABC'); -- ✅ 成功
INSERT INTO T_PK_PAD1 VALUES (2, 'ABC '); -- ✅ 成功
INSERT INTO T_PK_PAD1 VALUES (3, 'ABC '); -- ✅ 成功
COMMIT;
SELECT ID, '[' || CODE || ']' AS CODE_PADDED FROM T_PK_PAD1;
-- 输出:1 [ABC] / 2 [ABC ] / 3 [ABC ]
-- =====================================================
-- BLANK_PAD_MODE=0 实例
-- =====================================================
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
CREATE TABLE T_PK_PAD0 (
ID INT PRIMARY KEY,
CODE VARCHAR(10) UNIQUE
);
INSERT INTO T_PK_PAD0 VALUES (1, 'ABC');
INSERT INTO T_PK_PAD0 VALUES (2, 'ABC '); -- ❌ 失败!违反唯一约束(视为与 'ABC' 相同)
INSERT INTO T_PK_PAD0 VALUES (3, 'ABC '); -- ❌ 失败!违反唯一约束
COMMIT;
SELECT ID, '[' || CODE || ']' AS CODE_PADDED FROM T_PK_PAD0;
-- 输出:1 [ABC]

-- 在两个实例上分别执行
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
SELECT ID, '[' || NAME || ']' AS NAME_PADDED
FROM T_PAD_EQUAL
WHERE NAME LIKE 'ABC%';
-- 结果:BLANK_PAD_MODE=0 和 BLANK_PAD_MODE=1 都返回 ID=1,2,3
-- 因为 LIKE 'ABC%' 匹配以 ABC 开头的所有字符串
-- 细化测试
-- 在BLANK_PAD_MODE=1的实例中
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC'; -- 只返回 ID=1(精确长度匹配)
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC '; -- 只返回 ID=3
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC '; -- 只返回 ID=2
-- 在BLANK_PAD_MODE=0的实例中
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC'; -- 返回 ID=1,2,3(精确长度匹配)
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC '; -- 返回 ID=1,2,3
SELECT * FROM T_PAD_EQUAL WHERE NAME LIKE 'ABC '; -- 返回 ID=1,2,3

梳理 DM 初始化参数中哪些初始化后可以修改,哪些不能修改。
| 参数 | 说明 | 原因 |
|---|---|---|
| PAGE_SIZE | 页大小(4/8/16/32 KB) | 决定了数据文件的物理存储结构 |
| CHARSET / UNICODE_FLAG | 字符集(0=GB18030, 1=UTF-8,2=EUC-KR) | 决定了数据存储的编码方式 |
| CASE_SENSITIVE | 大小写敏感(Y/N) | 决定了系统表的字典序存储方式 |
| LENGTH_IN_CHAR | VARCHAR 长度以字符为单位(0/1) | 影响数据字典中列的定义方式 |
| EXTENT_SIZE | 簇大小(16/32/64) | 物理存储分配的基本单位 |
| BLANK_PAD_MODE | 空格填充模式 | 固化在数据文件元数据中,直接决定字符串索引、唯一约束的底层比较逻辑 |
# 编辑 dm.ini 文件
vi /test/DMpage4k/DMTEST4K/dm.ini
# 可修改的参数示例:
# COMPATIBLE_MODE = 0 # 兼容模式
# ENABLE_ENCRYPT = 0 # 加密开关
# MAX_SESSIONS = 100 # 运行参数
# BUFFER = 4000
# ... 等大量运行时可调参数
-- 查看可在线修改的参数
SELECT * FROM V$DM_INI WHERE PARA_TYPE = 'IN FILE';
-- 动态修改参数(示例)
-- 修改 COMPATIBLE_MODE 为 Oracle 兼容模式
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='COMPATIBLE_MODE';
SP_SET_PARA_VALUE(2, 'COMPATIBLE_MODE', 2);
-- 修改后查询确认
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'COMPATIBLE_MODE';
-- 结果:
/*
SQL> SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='COMPATIBLE_MODE';
行号 PARA_VALUE
---------- ----------
1 0
已用时间: 23.669(毫秒). 执行号:4001.
SQL> SP_SET_PARA_VALUE(2, 'COMPATIBLE_MODE', 2);
DMSQL 过程已成功完成
已用时间: 42.771(毫秒). 执行号:4002.
SQL> SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'COMPATIBLE_MODE';
行号 PARA_NAME PARA_VALUE
---------- --------------- ----------
1 COMPATIBLE_MODE 0
已用时间: 22.693(毫秒). 执行号:4003.
SQL> exit
[dmdba@localhost bin]$ ./DmS
DmServiceDMSERVER DmServiceDMTEST4K DmServiceDMTEST_CSY DmServiceDMTEST_PAD1
DmServiceDMTEST16K DmServiceDMTEST8K DmServiceDMTEST_GB18030 DmServiceDMTEST_UTF8
DmServiceDMTEST32K DmServiceDMTEST_CSN DmServiceDMTEST_PAD0 DmSingleRowMaxTester.java
[dmdba@localhost bin]$ ./DmServiceDMTEST4K restart
Stopping DmServiceDMTEST4K: [ OK ]
Starting DmServiceDMTEST4K: [ OK ]
[dmdba@localhost bin]$ ./disql SYSDBA/Sysdba123.@127.0.0.1:5237
服务器[127.0.0.1:5237]:处于普通打开状态
登录使用时间 : 12.348(ms)
disql V8
SQL> SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='COMPATIBLE_MODE';
行号 PARA_VALUE
---------- ----------
1 2
已用时间: 37.586(毫秒). 执行号:501.
*/

-- 方法一:通过 ALTER SYSTEM SET
-- 尝试修改 BLANK_PAD_MODE(失败)
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
/*
SQL> SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='BLANK_PAD_MODE';
行号 PARA_VALUE
---------- ----------
1 0
已用时间: 41.399(毫秒). 执行号:3103.
*/
ALTER SYSTEM SET 'BLANK_PAD_MODE' = 1;
-- 结果:报错,该参数不可修改
/*
SQL> ALTER SYSTEM SET 'BLANK_PAD_MODE' = 1;
ALTER SYSTEM SET 'BLANK_PAD_MODE' = 1;
[-836]:不可修改的配置参数.
已用时间: 10.068(毫秒). 执行号:0.
*/
-- 尝试修改LENGTH_IN_CHAR(失败)
SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='LENGTH_IN_CHAR';
/*
SQL> SELECT PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='LENGTH_IN_CHAR';
行号 PARA_VALUE
---------- ----------
1 0
已用时间: 25.098(毫秒). 执行号:3107.
*/
ALTER SYSTEM SET 'LENGTH_IN_CHAR' = 1;
-- 结果:报错,该参数不可修改
/*
SQL> ALTER SYSTEM SET 'LENGTH_IN_CHAR' = 1;
ALTER SYSTEM SET 'LENGTH_IN_CHAR' = 1;
[-836]:不可修改的配置参数.
已用时间: 2.007(毫秒). 执行号:0.
*/
-- 方法二:查询参数类型
SELECT
PARA_NAME,
PARA_TYPE,
PARA_VALUE,
CASE PARA_TYPE
WHEN 'READ ONLY' THEN '只读,不可修改'
WHEN 'IN FILE' THEN '静态参数,修改后需重启'
WHEN 'SYS' THEN '动态参数,可在线修改'
WHEN 'SESSION' THEN '会话级参数'
ELSE PARA_TYPE
END AS MODIFIABLE
FROM V$DM_INI
WHERE PARA_NAME IN (
'PAGE_SIZE',
'CHARSET',
'CASE_SENSITIVE',
'LENGTH_IN_CHAR',
'EXTENT_SIZE',
'BLANK_PAD_MODE',
'COMPATIBLE_MODE',
'MAX_SESSIONS',
'BUFFER'
)
ORDER BY PARA_NAME;
-- 结果:
行号 PARA_NAME PARA_TYPE PARA_VALUE MODIFIABLE
---------- --------------- --------- ---------- ---------------------------------
1 BLANK_PAD_MODE READ ONLY 0 只读,不可修改
2 BUFFER IN FILE 4000 静态参数,修改后需重启
3 COMPATIBLE_MODE IN FILE 0 静态参数,修改后需重启
4 LENGTH_IN_CHAR READ ONLY 0 只读,不可修改
5 MAX_SESSIONS IN FILE 10000 静态参数,修改后需重启
-- 此处不显示PAGE_SIZE、CHARSET、CASE_SENSITIVE、EXTENT_SIZE这几个参数是因为它们属于建库参数,不在dm.ini里,所以查不到


| 参数 | 分类 | 是否可修改 | 修改方式 | 版本说明 |
|---|---|---|---|---|
| PAGE_SIZE | 物理结构 | ❌ 不可修改 | — | 需重建实例 |
| CHARSET | 编码方式 | ❌ 不可修改 | — | 需重建实例 |
| CASE_SENSITIVE | 字典序 | ❌ 不可修改 | — | 需重建实例 |
| LENGTH_IN_CHAR | 元数据定义 | ❌ 不可修改 | — | 需重建实例 |
| EXTENT_SIZE | 物理存储 | ❌ 不可修改 | — | 需重建实例 |
| BLANK_PAD_MODE | 比较语义 | ❌ 不可修改 | — | 需重建实例 |
| COMPATIBLE_MODE | 兼容模式 | ✅ 可修改 | dm.ini(重启生效) | — |
| MAX_SESSIONS | 运行参数 | ✅ 可修改 | dm.ini(重启生效) | — |
| BUFFER | 缓存参数 | ✅ 可修改 | dm.ini(重启生效) | — |
| ENABLE_ENCRYPT | 加密开关 | ✅ 可修改 | dm.ini(重启生效) | — |
-- 在已初始化的任意实例中执行此脚本,确认各个参数的 PARA_TYPE
SELECT
PARA_NAME AS "参数名",
PARA_VALUE AS "当前值",
PARA_TYPE AS "参数类型",
DESCRIPTION AS "说明"
FROM V$DM_INI
WHERE PARA_NAME IN (
'GLOBAL_PAGE_SIZE', 'CHARSET', 'CASE_SENSITIVE',
'LENGTH_IN_CHAR', 'BLANK_PAD_MODE', 'EXTENT_SIZE',
'COMPATIBLE_MODE', 'MAX_SESSIONS', 'BUFFER',
'ENABLE_ENCRYPT', 'CTAB_SEL', 'PK_WITH_CLUSTER'
)
ORDER BY PARA_TYPE, PARA_NAME;
/*
SQL> SELECT
PARA_NAME AS "参数名",
PARA_VALUE AS "当前值",
PARA_TYPE AS "参数类型",
DESCRIPTION AS "说明"
FROM V$DM_INI
WHERE PARA_NAME IN (
'GLOBAL_PAGE_SIZE', 'CHARSET', 'CASE_SENSITIVE',
'LENGTH_IN_CHAR', 'BLANK_PAD_MODE', 'EXTENT_SIZE',
'COMPATIBLE_MODE', 'MAX_SESSIONS', 'BUFFER',
'ENABLE_ENCRYPT', 'CTAB_SEL', 'PK_WITH_CLUSTER'
)
ORDER BY PARA_TYPE, PARA_NAME;2 3 4 5 6 7 8 9 10 11 12 13
行号 参数名 当前值 参数类型 说明
---------- ---------------- --------- ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
1 BUFFER 4000 IN FILE Initial System Buffer Size In Megabytes
2 COMPATIBLE_MODE 0 IN FILE Server compatible mode, 0:none, 1:SQL92, 2:Oracle, 3:MS SQL Server, 4:MySQL, 5:DM6, 6:Teradata, 7:PG, 8:DB2
3 ENABLE_ENCRYPT 0 IN FILE Encrypt Mode For Communication, 0: Without Encryption; 1: SSL Encryption and Authentication; 2: Only SSL Authentication; 3: GmSSL; 4: Only SSL Encryption
4 MAX_SESSIONS 10000 IN FILE Maximum number of concurrent sessions
5 BLANK_PAD_MODE 0 READ ONLY blank_pad_mode
6 GLOBAL_PAGE_SIZE 4096 READ ONLY global_page_size
7 LENGTH_IN_CHAR 0 READ ONLY Column max length in CHAR or BYTE, 0: in BYTE, 1: in CHAR
8 PK_WITH_CLUSTER 0 SESSION Default Flag For Primary Key With Cluster, 0: Non-Cluster; 1: Cluster
8 rows got
已用时间: 21.782(毫秒). 执行号:3701.
*/

| 编号 | 实例名 | 端口 | 测试主题 | PAGE_SIZE | CHARSET | CASE_SENSITIVE | BLANK_PAD_MODE |
|---|---|---|---|---|---|---|---|
| 1 | DMTEST4K | 5237 | 页大小 | 4K | UTF-8 | Y | 1 |
| 2 | DMTEST8K | 5238 | 页大小 | 8K | UTF-8 | Y | 1 |
| 3 | DMTEST16K | 5239 | 页大小 | 16K | UTF-8 | Y | 1 |
| 4 | DMTEST32K | 5240 | 页大小 | 32K | UTF-8 | Y | 1 |
| 5 | DMTEST_UTF8 | 5241 | 字符集 | 8K | UTF-8 | Y | 1 |
| 6 | DMTEST_GB18030 | 5242 | 字符集 | 8K | GB18030 | Y | 1 |
| 7 | DMTEST_CSY | 5243 | 大小写 | 8K | UTF-8 | Y | 1 |
| 8 | DMTEST_CSN | 5244 | 大小写 | 8K | UTF-8 | N | 1 |
| 9 | DMTEST_PAD1 | 5245 | 空格填充 | 8K | UTF-8 | Y | 1 |
| 10 | DMTEST_PAD0 | 5246 | 空格填充 | 8K | UTF-8 | Y | 0 |
第 1 步:初始化实例 1 ~ 4(页大小测试)并完成测试
第 2 步:初始化实例 5 ~ 6(字符集测试)并完成测试
第 3 步:初始化实例 7 ~ 8(大小写测试)并完成测试
第 4 步:初始化实例 9 ~ 10(空格填充测试)并完成测试
第 5 步:在任意实例(1)中执行参数可修改性查询
https://eco.dameng.com
文章
阅读量
获赞
