人大金仓kingbase invalid value for parameter client_encoding ANSI_X3.4-1968

人大金仓kingbase invalid value for parameter client_encoding ANSI_X3.4-1968

背景

应用连接数据库的时候提示以下错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource': Invocation of init method failed; nested exception is com.kingbase8.util.KSQLException: ������������: ������ "client_encoding" ������������: "ANSI_X3.4-1968"
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.cloud.autoconfigure.RefreshAutoConfiguration$JpaInvokerConfiguration.init(RefreshAutoConfiguration.java:120)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
    ... 26 common frames omitted

怀疑问题

  1. jdbc驱动连接没有设置和数据库一致的编码

    人大金仓的资料实在是少,甚至如何在jdbc连接设置编码都无法找到,但是我们可以查找kingbase://协议,看看别人是怎么写的,发现是这样写的:

    *jdbc:kingbase8*://***:5419/cdb?useUnicode=true&characterEncoding=utf-8。于是改上去,并没有用。排除改方向

  2. Druid不支持kingbase8

    在百度确实找到了这个说法,但是官网上不去,没办法验证这个说法。而且本地可以正常连接,服务器连接不正常。排除改方向

解决步骤

  1. 解决初始化连接返回的乱码信息

    com.kingbase8.util.KSQLException: ������������: ������ "client_encoding" ������������: "ANSI_X3.4-1968"

    在以上信息可以看到,这个应该是链接的时候返回的,第一反应就是去查看kingbase日志:/data/kingbase/ES/V8/data/sys_log。可以看到如下信息:

    2021-04-14 16:18:43 CST 致命错误:  参数 "client_encoding" 的值无效: "ANSI_X3.4-1968"

    终于发现错误本体了,但是,是什么导致了乱码?乱码肯定是中文不是英文了,所以应该有什么地址可以设置日志的编码。不过kingbase基本和postgresql一致,所以按照postgresql的方法修改日志的编码即可。大致找了下kingbase的日志,发现在这个文件kingbase.conf

    修改kingbase.conf日志编码

    lc_messages = 'zh_CN.UTF-8'

    修改成:

    lc_messages = 'en_US.UTF-8'

    重启kingbase:sudo systemctl restart kingbase

    之后可以看到java的日志打印正常了:

    FATAL: invalid value for parameter "client_encoding": "ANSI_X3.4-1968"

  2. 调试源码

    根据提示信息查找,发现并没有查看到有用的信息,所以尝试调试源码

    在以下文件的对应方法[com.kingbase8.core.v3.ConnectionFactoryImpl#openConnectionImpl]找到了108行关键代码:

    newStream = new KBStream(socketFactory, hostSpec, connectTimeout);
    String client_encoding;
    if (KBProperty.CLIENT_ENCODING.get(info) == null) {
    client_encoding = System.getProperty("file.encoding");
    info.setProperty("clientEncoding", client_encoding);
    LOGGER.log(Level.FINE, "Use current JVM default encoding {0}", client_encoding);
    }
    
    client_encoding = KBProperty.CLIENT_ENCODING.get(info);
    newStream.setEncoding(Encoding.getJVMEncoding(client_encoding));

    可以看到初始化连接的时候,获取了jvm_encoding。这里,我们可以调试一下,在容器下的jvm_encoding究竟是什么编码?

    可以使用arthas修改容器class文件打印以下,或者随便在启动的时候日志打印以下System.getProperty("file.encoding")。容器只记录日志的输出,所以可能使用System.out.println会无法显示。

  3. 修改docker的jvm_encoding

    在dockerfile添加以下代码即可:ENV JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8

    完整的Dockerfile大致如下:

    #FROM指令必须指定且需要在Dockerfile其他指令的前面,指定的基础image可以是官方远程仓库中的,也可以位于本地仓库
    FROM livingobjects/jre8
    # UTF-8 并配置环境
    ENV LANG C.UTF-8
    ENV JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8
    #使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用
    VOLUME /tmp
    #从src目录复制文件到容器的dest。其中src可以是Dockerfile所在目录的相对路径,也可以是一个URL,还可以是一个压缩包
    ADD target/*.jar app.jar
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    RUN echo 'Asia/Shanghai' >/etc/timezone
    #ADD wait-for-it.sh /wait-for-it.sh
    RUN bash -c 'touch /app.jar'
    #指定Docker容器启动时执行的命令,可以多次设置,但是只有最后一个有效。
    ENTRYPOINT ["java","-Dfile.encoding=UTF8","-jar","/app.jar","--spring.profiles.active=test","&"]
  4. 修改重新build了之后可以发现,连接正常了。

总结

  1. 网上关于人大金仓的资料比较少,如果遇到问题,可以尝试把关键字更换成postgresql再查看,也许更容易查找到答案
  2. 需要意识到容器化部署下一些参数不一致。
  3. 网上找不到答案可以从源码入手
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
这个问题通常出现在 PostgreSQL 数据库中。"client_encoding" 错误表明你的客户端连接尝试使用了一种不受支持的字符编码格式。要解决这个问题,你可以按照以下步骤进行操作: 1. 确保你的客户端使用的字符编码与 PostgreSQL 数据库的字符编码设置相匹配。你可以通过检查数据库的 "client_encoding" 参数来确定数据库当前使用的字符编码。可以使用以下 SQL 查询来获取该值:SELECT name, setting FROM pg_settings WHERE name = 'client_encoding'; 2. 如果你的客户端字符编码与数据库字符编码不匹配,你可以尝试更改客户端的字符编码设置。具体的步骤取决于你所使用的客户端工具。 3. 如果你正在使用 psql 命令行工具连接到 PostgreSQL 数据库,你可以在连接时指定字符编码。例如,使用以下命令连接到数据库:psql -U username -d dbname -h hostname --encoding=UTF8 4. 如果上述方法无效,你可以尝试更改 PostgreSQL 数据库的默认字符编码,使其与客户端匹配。这需要修改数据库的 "postgresql.conf" 配置文件。在该文件中,找到 "client_encoding" 参数并将其设置为与客户端匹配的值,然后重新启动数据库。 请注意,修改数据库的默认字符编码可能会对现有数据产生影响,因此在执行此操作之前,请务必备份你的数据并谨慎操作。此外,如果你不熟悉 PostgreSQL 数据库的配置和管理,请尽量寻求专业人士的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值