目 录CONTENT

文章目录

【GaussDB】使用MySQL客户端连接到GaussDB的M-Compatibility数据库

DarkAthena
2025-08-23 / 0 评论 / 0 点赞 / 5 阅读 / 0 字

【GaussDB】使用MySQL客户端连接到GaussDB的M-Compatibility数据库

概述

GaussDB 从内核 505.1 版本(2024年4月发布)起,新增了一种新的兼容模式 M-Compatibility,这是一种整体上比之前的B模式对MySQL兼容性更高的模式。这种M模式在建库时会自动使用模板库 templatem

之所以需要再新增一种M模式,我猜测是因为GaussDB发现有些MySQL兼容性已经完全违背了内核的SQL及存储逻辑,无法通过参数调整进行兼容,为了不影响原有B模式的用户,必须新增一种兼容模式来隔离之前的逻辑。

新的这个M兼容模式,可以用MySQL客户端进行连接,但是实际使用过程中,可能会有一些坑在文档中并未详细说明,本文就来介绍一下"使用MySQL客户端连接到GaussDB的M-Compatibility数据库"的正确姿势。

测试环境:本文使用的GaussDB内核版本为 506.0 SPC0100


建库操作

指定M兼容模式建库:

CREATE DATABASE mysql DBCOMPATIBILITY='M';

修改参数

参考文档

添加客户端IP到数据库白名单

将客户端IP添加到数据库白名单,具体操作请联系管理员处理。

设置兼容性参数

请参见《管理员指南》中的"配置运行参数"章节,配置相关GUC参数并重启数据库。

参数配置:

  1. 配置协议监听的TCP端口号,设置GUC参数 plat_compat_server_port 为合理端口
  2. 如果使用到RSA,需要设置GUC参数 plat_compat_allow_public_key_retrievalon
  3. 将GUC参数 m_format_dev_version 设置为 "s2"

执行命令:

gs_guc reload -I all -N all -c "plat_compat_server_port=3306"
gs_guc reload -I all -N all -c "plat_compat_allow_public_key_retrieval=on"
gs_guc reload -I all -N all -c "m_format_dev_version='s2'"

创建连接用户(可选)

CREATE USER mysql_user PASSWORD 'Gaussdb@123' SYSADMIN MONADMIN;

连接测试

初始连接问题

image-grwl.png
使用MySQL客户端连接时出现报错:

错误信息: plat_compat_b_conn_handshake, handshake error.

Java代码连接测试

尝试手写一段Java代码进行连接:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class MySQLCreateTable {
    public static void main(String[] args) {
        String url = "jdbc:mysql://192.168.163.119:3306/mysql";
        String user = "mysql_user";
        String password = "Gaussdb@123";

        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement()) {

            String sql = "CREATE TABLE IF NOT EXISTS users2 (" +
                         "id INT PRIMARY KEY AUTO_INCREMENT," +
                         "name VARCHAR(100) NOT NULL," +
                         "email VARCHAR(100) NOT NULL UNIQUE" +
                         ")";
            stmt.executeUpdate(sql);
            System.out.println("Table created successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果: 也报错了

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
        at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:827)
        at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:447)
        at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237)
        at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:681)
        at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:229)
        at MySQLCreateTable.main(MySQLCreateTable.java:11)
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
        at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
        at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:340)
        at com.mysql.cj.protocol.a.NativeAuthenticationProvider.negotiateSSLConnection(NativeAuthenticationProvider.java:777)
        at com.mysql.cj.protocol.a.NativeAuthenticationProvider.proceedHandshakeWithPluggableAuthentication(NativeAuthenticationProvider.java:486)
        at com.mysql.cj.protocol.a.NativeAuthenticationProvider.connect(NativeAuthenticationProvider.java:202)
        at com.mysql.cj.protocol.a.NativeProtocol.connect(NativeProtocol.java:1348)
        at com.mysql.cj.NativeSession.connect(NativeSession.java:163)
        at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:947)
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:817)
        ... 6 more
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
        at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:172)
        at java.base/sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:103)
        at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:240)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:448)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
        at com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:316)
        at com.mysql.cj.protocol.StandardSocketFactory.performTlsHandshake(StandardSocketFactory.java:188)
        at com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.java:99)
        at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:331)
        ... 13 more

解决方案

查看官方文档《基于MySQL JDBC开发-开发步骤-连接数据库-以常规方式连接》,发现文档中的连接串是:

String sourceURL = "jdbc:mysql://$ip:$port/database?useSSL=false&allowPublicKeyRetrieval=true";

多了两个参数,逐步测试:

步骤1:添加 useSSL=false

先加一个 useSSL=false 参数测试。
image-kjpz.png
结果: 出现了和mogeaver一样的报错。

步骤2:添加 allowPublicKeyRetrieval=true

再把另一个参数也加上去 allowPublicKeyRetrieval=true
image-mrai.png
结果: ✅ 执行成功了!

验证其他客户端

在mogeaver里也加上这个参数 allowPublicKeyRetrieval=true
image-jlyz.png
结果: ✅ 也连接成功了!

说明: 但是mogeaver里的useSSL为true,之所以没有报错,是因为mogeaver里还自动加上了enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2

连接参数总结

根据测试,自己写的Java代码,连接时必须加上:

  • 方案一: useSSL=false&allowPublicKeyRetrieval=true
  • 方案二: useSSL=true&enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2

常见问题及解决

如果是普通的测试人员,测到这里,就会认为连接测试这一项已经测试通过了,但是换几个不同的环境里的GaussDB去测,还可能会出现这样的报错:

问题:Access denied for user

image-itil.png

错误信息: Access denied for user

注意: 如果是用户名密码错误,也会报这个错,所以先要用gsql测试一下用户名密码是否正确,确认用户名密码没有写错后,那么问题就可能发生在密码加密方式上。

原因分析

在官方文档[《配置客户端接入认证》](https://support.huawei.com/carrier/docview?nid=DOC1101458028&path=PBI1-253383977/PBI1-23710112/PBI1-23710137/PBI1-256197501&partNo=k00e)这个章节里写着:

外部客户端使用M-Compatibility兼容协议远程连接M-Compatibility数据库时,只支持 sha256认证方式

于是去检查gs_hba.conf,发现无论是配置成md5还是sha256,Access denied for user这个问题都依然存在。

然后继续翻官方文档,发现在《设置密码安全策略》这个章节里写着:

使用M-Compatibility兼容协议连接数据库时,仅支持sha256加密模式,即 password_encryption_type = 2

也就是说,必须确保数据库用户的密码存储时,必须是仅存储sha256密文,不能支持其他方式。

解决步骤

  1. 修改密码加密参数:
gs_guc reload -I all -N all -c "password_encryption_type=2"
  1. 重新设置用户密码:
ALTER USER mysql_user PASSWORD 'mysql_123';

到此,使用MySQL客户端连接GaussDB就顺利了...吗?


进阶配置:RSA加密支持

搜索官方文档,发现还有这么一个章节:《使用RSA加密登录密码》

RSA加密登录配置要求:

  1. 设置 plat_compat_allow_public_key_retrieval 参数值为 on
  2. 设置 require_ssl 参数值为 off
  3. 设置 hba type 参数值为 hosthostnossl

也就是说,如果 require_sslon,那么本文的配置方式也会连接不上去了。

连接方式总结

综合分散在文档各个地方的信息来看,连接应该是可以用RSA或者不用RSA:

服务端配置客户端配置说明
plat_compat_allow_public_key_retrieval=offuseSSL=true&enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2禁用RSA,使用SSL
plat_compat_allow_public_key_retrieval=onuseSSL=false&allowPublicKeyRetrieval=true使用RSA,不使用SSL
plat_compat_allow_public_key_retrieval=onuseSSL=true&enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2允许使用RSA,但仍然使用SSL

实测也的确如此。


补充说明

另外,数据库里还有个参数 plat_compat_default_database,可以配置MySQL协议连过来需要连接哪个库。

  • 在没有设置这个参数时: JDBC连接串里的dbname就真的是GaussDB里面的数据库名称
  • 如果设置了这个参数: JDBC连接串里的dbname就是 plat_compat_default_database 指定的库下的schema名称

重要声明

⚠️ 版本说明:本文这里的这些内容,仅为在 506.0 SPC0100 集中式版本上测试的结果,不代表新版本的表现(目前已知有些东西在新版本改了)。


相关文档

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论