一、引言

项目落地银行有信创要求,需要将 Nacos 依赖的外源数据库从 MySQL 更换为达梦数据库。Nacos 官方不支持达梦数据库,需要修改源码进行适配。

二、正文

2.1 数据库准备

  1. 下载镜像

    官方镜像地址:dm8_20240715_x86_rh6_rq_single.tar

  2. 加载镜像

    # 镜像上传到服务器后,执行加载命令
    docker load -i dm8_20240715_x86_rh6_rq_single.tar
  3. 容器启动

    # 默认用户密码:SYSDBA/SYSDBA001
    docker run -d \
        -p 5236:5236 \
        --restart=always \
        --name=dm8 \
        --privileged=true \
        -e LD_LIBRARY_PATH=/opt/dmdbms/bin \
        -e PAGE_SIZE=16 \
        -e EXTENT_SIZE=32 \
        -e LOG_SIZE=1024 \
        -e UNICODE_FLAG=1 \
        -e INSTANCE_NAME=dm8 \
        -v /opt/dmdbms/data:/opt/dmdbms/data \
        dm8_single:dm8_20240715_rev232765_x86_rh6_64

2.2 集成达梦驱动

  1. 下载依赖

    可以选择在达梦官网或者Maven中央仓库下载:

    • 达梦官网驱动地址:jdbc-20240326.zip

      mvn install:install-file -Dfile=E:\dmdbms\drivers\jdbc\DmJdbcDriver18.jar -DgroupId=com.dameng -DartifactId=DmJdbcDriver18 -Dversion=8.1.3.140 -Dpackaging=jar
    • Maven中央仓库:DmJdbcDriver18
  2. 添加依赖

    在nacos-all的pom中指定添加如下内容

    <DmJdbcDriver18.version>8.1.2.192</DmJdbcDriver18.version>
    
    <dependency>
        <groupId>com.dameng</groupId>
        <artifactId>DmJdbcDriver18</artifactId>
        <DmJdbcDriver18.version>8.1.3.140</DmJdbcDriver18.version>
    </dependency>

    在nacos-config、nacos-naming 两个模块添加依赖:

    <dependency>
        <groupId>com.dameng</groupId>
        <artifactId>DmJdbcDriver18</artifactId>
    </dependency>

2.3 初始化数据库

Nacos团队提供了达梦初始化脚本供参考:nacos-dm.sql,但其中有一些错误。

# 脚本把NACOS错写成NOCOS了,可以直接把脚本中的NOCOS去掉

# 复制脚本到容器容器
docker cp nacos-dm.sql dm8:/opt/dmdbms/data/

# 进入容器
docker exec -it dm8 bash

# 使用disql执行初始化脚本
CREATE USER "nacos" IDENTIFIED BY "NACOS1234";
/opt/dmdbms/bin/disql nacos/NACOS1234
start /opt/dmdbms/data/nacos-dm.sql

该文件需要被放置到文件夹~\nacos-2.2.3\distribution\conf\下,打包的时候会一块打包进来。

2.4 修改源码

本次适配基于Nocos 2.2.3版本,可以根据自己需求拉取相应版本的代码:Nacos-2.2.3

利用 SPI 的原理,自定义实现各个表的 Mapper 实现类。

将nacos-datasource-plugin里的mysql的mapper文件复制到新的dm文件夹下改名,并修改将相应的常量和配置,具体如下:

~\nacos-2.2.3\plugin\datasource\src\main\java\com\alibaba\nacos\plugin\datasource\constants\DataSourceConstant.java

public class DataSourceConstant {
    public static final String MYSQL = "mysql";

    public static final String DERBY = "derby";
    // 添加一行
    public static final String DM = "dm";
}

~\nacos-2.2.3\plugin\datasource\src\main\java\com\alibaba\nacos\plugin\datasource\impl\dm\ConfigInfoAggrMapperByDm.java

public class ConfigInfoAggrMapperByDm extends AbstractMapper implements ConfigInfoAggrMapper {
    
    @Override
    public String findConfigInfoAggrByPageFetchRows(int startRow, int pageSize) {
        return "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE data_id= ? AND "
                + "group_id= ? AND tenant_id= ? ORDER BY datum_id LIMIT " + startRow + "," + pageSize;
    }
    
    @Override
    public String getDataSource() {
        return DataSourceConstant.DM;
    }
}

~\nacos-2.2.3\plugin\datasource\src\main\resources\META-INF\services\com.alibaba.nacos.plugin.datasource.mapper.Mapper

# 添加如下内容
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoAggrMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigTagsRelationMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.HistoryConfigInfoMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoTagMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoMapperByMyDm
com.alibaba.nacos.plugin.datasource.impl.dm.ConfigInfoBetaMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.TenantInfoMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.TenantCapacityMapperByDm
com.alibaba.nacos.plugin.datasource.impl.dm.GroupCapacityMapperByDm

2.5 修改启动配置

~\Java\nacos-2.2.3\console\src\main\resources\application.properties

# application.properties配置
spring.datasource.platform=dm
spring.sql.init.platform=dm
db.num=1

db.pool.config.driverClassName=dm.jdbc.driver.DmDriver
db.url.0=jdbc:dm://192.168.102.115:30236
db.user=nacos
db.password=NACOS1234

2.6 本地运行Nacos

找到 com.alibaba.nacos.Nacos类,启动即可。需要在启动选项的VM options中加上-Dnacos.standalone=true

修改启动选项

本地启动

2.7 打包并运行

Nacos源码打包命令

# 打包一定要选择CMD而不是PowerShell执行,不然会报错
mvn -Prelease-nacos -Dmaven.test.skip=true -Dpmd.skip=true -Dcheckstyle.skip=true clean install -U

成功后,nacos包会在~\nacos\distribution\target\目录下:

介质目录

重新解压nacos-2.2.3.zip,修改conf\application.properties,然后执行启动脚本

# windows环境
startup.cmd -m standalone

# linux环境
startup.sh -m standalone

三、遇到的问题

3.1 执行打包脚本失败

  • 报错

    [ERROR] Unknown lifecycle phase “.test.skip=true“. You must specify a valid lifecycle phase or a ...

  • 原因

    我的IdeaUI命令行默认打开powerShell而不是Command Prompt

  • 方案

    改用CMD而不是PowerShell执行打包命令

3.2 新增文件没有凭证

  • 报错

    Too many files with unapproved license

  • 原因

    新增文件没有协议头导致报错

  • 方案

    新增的代码文件头部加入以下内容

    /*
     * Copyright 1999-2022 Alibaba Group Holding Ltd.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

3.3 更新配置信息,提示违反唯一性约束

  • 报错

    caused: PreparedStatementCallback; 违反表[CONFIG_INFO]唯一性约束; nested exception is dm.jdbc.driver.DMException: 违反表[CONFIG_INFO]唯一性约束;caused: 违反表[CONFIG_INFO]唯一性约束

  • 原因

    见官方仓库issue:#12289和#10335,insertOrUpdate操作捕获的异常从2.2.1开始从DataIntegrityViolationException改为DuplicateKeyException,而达梦不会抛出DuplicateKeyException异常并处理,导致异常直接抛到上层了。

  • 方案

    • 方案一:参考提交Handling DataIntegrityViolationException and DuplicateKey#11405修改文件~/nacos/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java

      主要将两处涉及DuplicateKeyException的异常捕获做进一步捕获并处理。将

              } catch (DuplicateKeyException ive) { // Unique constraint conflict
                  return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo);
              }

      改为

              } catch (DuplicateKeyException ignore) {
                  // Must be unique constraint conflict.
                  return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo);
              } catch (DataIntegrityViolationException dive) {
                  // Might be unique constraint conflict or some of other data integrity violation. try to update.
                  try {
                      return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo);
                  } catch (Exception e) {
                      LogUtil.FATAL_LOG
                              .error("[db-error] try to update config failed, with DataIntegrityViolationException, {}",
                                      dive.getMessage(), e);
                      throw e;
                  }
              }
    • 方案二:基于Nacos 2.3及以上版本进行达梦数据库的适配

四、附录

达梦数据库建表规范(临时)

  • 表名和字段名均需要COMMENT,且能清晰的标注表名和字段名的含义
  • 数据表如果使用显式主键,无特殊情况下要求使用非自增,snowflake生成
  • boolean使用tinyint(为了跨平台兼容),使用is开头
  • 逻辑删除的字段,建议使用is_deleted或enabled等字段
  • 不使用包括但不限于DOMAIN、VERIFY等达梦数据库的保留关键字作为字段名和表名
  • varchar根据长度酌情使用8、32、50、128、255等几个范围,超长使用text,避免空间浪费

五、参考文献

最后修改:2026 年 09 月 14 日
如果觉得我的文章对你有用,请随意赞赏