近期因项目需要,要适配flowable到国产数据库TiDB,将碰到的问题做个记录,虽然问题暂时解决了,但不是最优解,如有更好的配置方法,烦请指教!

版本

flowable:6.4.2版本

tidb:7.5版本

问题描述

由于tidb完全兼容mysql,所以系统连接和mysql一致,本来以为不用做任何修改,将mysql导入到tidb后本地windows环境直接启动系统发现正常,但部署到linux服务器后无法正常启动,报如下错误:

FlowableWrongDbException: version mismatch: library version is ‘6.5.0.1‘, db version is 5.99.0.0 

解决思路

由于这个错在以前连接mysql时碰到过,当时的原因是mysql大小写敏感问题导致的,需要配置lower_case_table_names参数,所以这边猜测也是这个原因,于是看了tidb官方文档,描述如下:

tidb对lower_case_table_names 参数为2的描述是 :

表名存储为给定的大小写但是比较的时候是小写的。

参考:TiDB 产品文档 | PingCAP 文档中心

这边尝试将lower_case_table_names参数的值设置成1,没报错,但还是没效果,没办法,这边只能调试flowable源码,最后发现是 isTablePresent 这个方法没有找不到表名:

    public boolean isTablePresent(String tableName) {
        // ACT-1610: in case the prefix IS the schema itself, we don't add the
        // prefix, since the check is already aware of the schema
        DbSqlSession dbSqlSession = getDbSqlSession();
        DbSqlSessionFactory dbSqlSessionFactory = dbSqlSession.getDbSqlSessionFactory();
        if (!dbSqlSession.getDbSqlSessionFactory().isTablePrefixIsSchema()) {
            tableName = prependDatabaseTablePrefix(tableName);
        }

        Connection connection = null;
        try {
            connection = dbSqlSession.getSqlSession().getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            ResultSet tables = null;

            String catalog = dbSqlSession.getConnectionMetadataDefaultCatalog();
            if (dbSqlSessionFactory.getDatabaseCatalog() != null && dbSqlSessionFactory.getDatabaseCatalog().length() > 0) {
                catalog = dbSqlSessionFactory.getDatabaseCatalog();
            }

            String schema = dbSqlSession.getConnectionMetadataDefaultSchema();
            if (dbSqlSessionFactory.getDatabaseSchema() != null && dbSqlSessionFactory.getDatabaseSchema().length() > 0) {
                schema = dbSqlSessionFactory.getDatabaseSchema();
            } else if (dbSqlSessionFactory.isTablePrefixIsSchema() && StringUtils.isNotEmpty(dbSqlSessionFactory.getDatabaseTablePrefix())) {
                schema = dbSqlSessionFactory.getDatabaseTablePrefix();
                if (StringUtils.isNotEmpty(schema) && schema.endsWith(".")) {
                    schema = schema.substring(0, schema.length() - 1);
                }
            }

            String databaseType = dbSqlSessionFactory.getDatabaseType();

            if ("postgres".equals(databaseType)) {
                tableName = tableName.toLowerCase();
            } else if ("cockroachdb".equals(databaseType)) {
                tableName = tableName.toLowerCase(); // same as postgres
                schema = "public"; // CRDB only supports public right now
            }

            if (schema != null && "oracle".equals(databaseType)) {
                schema = schema.toUpperCase();
            }

            if (catalog != null && catalog.length() == 0) {
                catalog = null;
            }

            try {
                //分别在控制台打印出catalog, schema, tableName的值
//                System.out.println("catalog: " + catalog);
//                System.out.println("schema: " + schema);
//                System.out.println("tableName: " + tableName);
                tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES);
                return tables.next();
            } finally {
                try {
                    if (tables != null) {
                        tables.close();
                    }
                } catch (Exception e) {
                    logger.error("Error closing meta data tables", e);
                }
            }

        } catch (Exception e) {
            throw new FlowableException("couldn't check if tables are already present using metadata: " + e.getMessage(), e);
        }
    }

以上方法是flowable检查是否存在物理表的方法,最终定位到是以下方法没有获取到表名:

这边增加日志后,打印输出如下:

flowable对以上3张表做了验证,并且验证后直接报错。

由于这几张物理表建表时是用的小写,我怀疑可能是这的问题,于是这边把act_de_property,act_id_property,act_hi_procinst,act_ru_execution这几张表删除后用大写的表名重建后再重启服务发现正常。

总结

tidb官网说明是 lower_case_table_names 不区分windows和linux,但实际还是有区别,我理解是windows下默认还是大小写不敏感,但linux下还是大小写敏感导致的,不然也不会出现本地windows环境正常,而部署到linux无法启动。

如有其他解决办法,欢迎留言!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐