liquibase兼容达梦(DM8)问题记录

liquibase是一款很优秀的开源数据库版本管理工具,他可以帮助开发者处理产品各版本间数据库结构及数据的差异,形成数据库版本差异,这样即可在不同的版本间执行migrate。

而随着国际形势的变化, 我们的需求也在逐渐向国产数据库转型,但测试发现,liquibase不支持达梦。于是我们尝试修改liquibase的源码进行适配性兼容。

使liquibase兼容达梦的思路很简单,因达梦描述自己属于Oracle Like数据库,大量语法结构与Oracle近似,故我们以liquibase的OracleDatabase类作为父类,在其基础上进行扩展。说的更详细一点,无非是让liquibase认为我们使用的是Oracle即可,然后再尝试修正一些具体的数据库差异就好。

所以,我们创建DM8Database,继承OracleDatabase类,同时尝试覆写getShortName、getDefaultDatabaseProductName、isCorrectDatabaseImplementation、getDefaultDriver等方法,示例代码如下:

@Override
public String getShortName() {
return PRODUCT_SHORT_NAME;
}

@Override
protected String getDefaultDatabaseProductName() {
return getDatabaseProductName();
}

@Override
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
}

@Override
public String getDefaultDriver(String url) {
if (url.startsWith(DRIVER_CONN_PERFIX)) {
return DRIVER_STRING;
}
return null;
}

@Override
public Integer getDefaultPort() {
return 5236;
}

当覆写完成后,我们执行,发现报错:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘liquibase’ defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migration failed for change set classpath:db/tabledefine/t_tf_apiinfo.xml::t_tf_apiinfo-1.0.0::zhangjian:
Reason:
classpath:/db/changelog.xml : liquibase.precondition.core.TableExistsPrecondition@fe7b6b0 : 第1 行附
近出现错误:
无效的表或视图名[ALL_REGISTERED_MVIEWS]

查阅资料发现Oracle中雾化视图存储于ALL_REGISTERED_MVIEWS中,而达梦中并不存在此表。于是修改liquibase源码,去除此针对此表的依赖;我跟踪代码到JdbcDatabaseSnapshot,fastFetchQuery方法,其中有调用queryOracle方法,我们覆写一个queryDameng方法,同时增加判断入口条件,当数据库为达梦时,执行queryDameng方法;

if (database instanceof DM8Database) {
return queryDameng(catalogAndSchema, view);
}

修改后,初始化没有问题了,但是当初始化完成后,再执行,却有在报空指针异常。

此问题的排查颇废了一番功夫,最后发现,问题出在DBA_TAB_COLS表的HIDDEN_COLUMN字段。在达梦数据库(DM8)中,此字段的默认值为NULL,而在Oracle中,此字段为NO。于是我们增加queryDameng方法,去除对HIDDEN_COLUMN字段的限制。

解决完此问题,基本的正常使用没问题了,但是达梦数据库(DM8)本身还存在大量的保留字,例如“context”也是保留字之一,于是我们覆写mustQuoteObjectName方法,按照达梦文档中提供的保留字进行处理,这样liquibase会自动对保留字进行引号处理。

至此,问题全部修正。最终修改后的包,见附件

RHEL中增加Oracle自启动

b

Oracle数据库默认服务器重启时候不跟随系统启动,现在需要令Oracle跟随系统自动启动,方法很简单。(以下方法在RHEL 5.4下测试通过。)

1、修改Oracle配置文件,允许指定实例通过dbstart,dbstop命令控制。

[bash]vi /etc/oratabdemo1:/oracle/app/product/10.2.0/db_1:N (将N该为Y)[/bash]

2、修改Oracle启停脚本,主要操作是指定Oracle监听的位置。(此操作需要切换到oracle用户进行。)
[bash]
<pre>su – oraclevi $ORACLE_HOME/bin
vi ./dbstart</pre>
[/bash]
找到ORACLE_HOME=这一行,将其修改为:
[bash]
ORACLE_HOME_LISTNER=$ORACLE_HOME
[/bash]
同样的道理需要修改dbstop中的相关路径。

3、测试Oracle启停脚本。
[bash]
dbstop
dbstart
[/bash]
4、编写脚本,令用户可以使用service命令控制Oracle启停。(此操作需要以root用户进行)
[bash]
vi /etc/rc.d/init.d/oracle
#!/bin/bash
export ORACLE_SID=demo1 
#将此改为要自启的Oracle的SID名。
export ORACLE_BASE=/oracle
#将此修改为安装Oracle的根目录,此目录可以通过在Oracle用户下执行echo $ORACLE_BASE获得。
export ORACLE_HOME=/oracle/app/product/10.2.0/db_1
#将此修改为Oracle的安装目录,此目录可以通过在Oracle用户下执行echo $ORACLE_HOME获得
export PATH=$PATH:$ORACLE_HOME/bin
case "$1" in
start)
su oracle -c $ORACLE_HOME/bin/dbstart
touch /var/lock/oracle
echo "OK"
;;
stop)
echo -n "Shutdown oracle: "
su oracle -c $ORACLE_HOME/bin/dbshut
rm -f /var/lock/oracle
echo "OK"
;;
*)
echo "Usage: ‘$0’ start|stop"
exit 1
esac
exit 0
[/bash]
保存退出
给予执行权限:
[bash]
chmod +x /etc/rc.d/init.d/oracle
[/bash]
5、将服务加入到自启动列表,并进行检查。
[bash]chkconfig –add oracle
chkconfig –list oracle[/bash]