环境
oceanbase 使用oracle模式。
nacos server版本为2.4,使用oceanbase作为nacos server数据库插件。
插件编译
nacos插件开发工程:https://github.com/nacos-group/nacos-plugin.git
在nacos-datasource-plugin-ext目录下有适配不同数据库的demo,这里看到有dameng、gassdb、postgresql、oracle、kingbase、mssql。由于这里oceabase使用的oracle模式,找到自己需要的oracle plugin模块,其他的不管可以删除掉或取消模块,省的影响编译。
自增主键问题
我们知道oracle 11g及以下版本没有自增主键机制,在nacos官方提供的oracle-schema.sql见表语句中其实是使用的序列+触发器机制来实现的主键自增。
这里稍微修改了下生产insert语句的实现,只用序列不用触发器。
具体代码在AbstractOracleMapper.insert()方法,原来的生成insert语句默认是不显示设置主键的值,这里在原来生产insert语句的基础上添加主键显示设置value。
java
@Override
public String insert(List<String> columns) {
String withoutIdTableStr = "permissions,roles,users";
String sql = super.insert(columns);
if (!withoutIdTableStr.contains(getTableName().toLowerCase())) {
String idName = "(id,";
String idVal = "VALUES(" + getTableName() + "_id_seq.nextval,";
if(getTableName().toLowerCase().contains("his_config_info")){
idName = "(nid,";
idVal = "VALUES(" + getTableName() + "_nid_seq.nextval,";
}
sql = sql.replaceFirst("\\(", idName).replaceFirst("VALUES\\(", idVal);
System.out.println(sql);
}
return sql;
}
这里做了一下表判断,permissions,roles,users这三个表是没有主键的。his_config_info这个历史配置表的主键名是nid,其他的表主键都是id。每个表主键对应序列名是:{tablename}_{主键名}__seq。这样就动态替换显示设置了主键为对应序列的nextval值。
这样打包当前oracle plugin会生产一个nacos-oracle-datasource-plugin-ext-1.0.0-SNAPSHOT.jar插件包,放到nacos server下plugins目录即可,jdbc的driver类可以打到上面的plugin包里,也可以单独包也放到plugins目录下即可。这里是使用的独立jar包oceanbase-client-2.4.13.jar。
修改server配置
nacos server对应conf/application.properties配置文件对应数据库连接信息改成oracle模式
properties
spring.datasource.platform=oracle
spring.datasource.platform=oracle
db.url.0=jdbc:oceanbase://ip:port
db.user=账号
db.password=密码
db.pool.config.connectionTestQuery=SELECT 1 FROM dual
这里一定要配置connectionTestQuery,这个默认hikar数据库连接池默认会使用该语句来验证数据库连接健康可用。默认是select 1 ,oracle数据库不支持。
另外在数据库连接串中还需要设置useOraclePrepareExecute=true,这样Preparestatmen执行语句会返回AutoGeneratedKey 。nacos 使用jdbcTemplate执行的sql。
到这里配置没问题的话,应该可以正常启动nacos server,进行配置的编辑。
- 问题1:
发现不展示配置的格式,数据库中格式存储是正确的,最后跟踪到是oracle版的plugin的查询语句没有查询type这一列,对应ConfigInfoMapperByOracle.findConfigInfoLike4PageFetchRows()方法在查询语句上加上type就可以了。
- 问题2:
另一个问题,在配置编辑发布的时候一直失败,提示"Cas publish fail,server md5 may have changed."。找到对应源码位置就是执行update语句,这句话以上应该就是执行失败了,根据现有md5值从库里查不到记录,无法完成更新。有用的信息很少,前面知道nacos使用的jdbcTemplate,这里为了查看具体错误sql语句和参数,需要配置日志级别
properties
logging.level.org.springframework.jdbc.core=DEBUG
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE
logging.level.com.alibaba.nacos.config.server.service.repository.extrnal=DEBUG
最后发现是sql语句中where条件设置的参数和列不对应,查询不到对应的记录。
具体方法是在ConfigInfoMapperByOracle.updateConfigInfoAtomicCas()。
其实update语句数据库间没有多大的差异,这里把这个方法实现删除,让他走默认的ConfigInfoMapper里的逻辑,从新打包编译部署下就可以。
nacos官方oracle plugin里明显的sql错误有这两处,看来使用的人不太多。