1.mycat2对longdata报文直接识别为byte[],不再进行转换处理
    2.对于prepare statement execute报文中的FIELD_TYPE_VARCHAR,会先使用utf8编码尝试进行转换,然后不是utf8编码,则当做byte[]处理
    3.jdbc启用服务器预处理的连接字符串是

    1. jdbc:mysql://localhost:8066/mysql?username=root&password=123456&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useServerPrepStmts=true

    4.在不开启服务器预处理的情况,以下情况是不支持

    1. Blob blob = jdbcConnection.createBlob();
    2. blob.setBytes(1,originalBytes);
    3. JdbcUtils.execute(jdbcConnection,"insert db1.testBlob (`blob`) values(?)",Arrays.asList(blob));

    Mycat会收到带有二进制数据的sql
    image.png
    为了解决这个问题,有两个办法

    办法1
    需要开启服务器预处理
    开启后,通过网络报文抓包可以观察到blob数据是额外发送的,不再嵌入的sql字符串内
    image.png

    办法2
    com.mysql.cj.ParseInfo#ParseInfo(java.lang.String, com.mysql.cj.Session, java.lang.String, boolean)
    boolean noBackslashEscapes = session.getServerSession().isNoBackslashEscapesSet();
    此处决定jdbc驱动使用binary嵌入二进制还是使用16进制编码嵌入

    而isNoBackslashEscapesSet是sql_mode决定的
    public boolean isNoBackslashEscapesSet() {
    String sqlModeAsString = this.serverVariables.get(“sql_mode”);
    return sqlModeAsString != null && sqlModeAsString.indexOf(“NO_BACKSLASH_ESCAPES”) != -1;
    }

    所以可以设置mycat的原型库的sql_mode,使isNoBackslashEscapesSet返回true

    查询现有sql_mode

    1. SELECT @@session.sql_mode;
    2. 结果例子
    3. ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    1. SET GLOBAL sql_mode ='NO_BACKSLASH_ESCAPES';
    2. //这里需要把原有的sql_mode添加上NO_BACKSLASH_ESCAPES
    3. SET GLOBAL sql_mode ='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_BACKSLASH_ESCAPES'

    也可以在my.cnf或者my.ini设置

    1. [mysqld]
    2. sql_mode=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_BACKSLASH_ESCAPES

    5.而在不开启或者开启服务器预处理的情况下,不设置sql_mode,这个情况都是支持的

    1. byte[] originalBytes = byteArrayOutputStream.toByteArray();
    2. JdbcUtils.execute(mycatConnection,"insert db1.testBlob (`blob`) values(?)",Arrays.asList(originalBytes));

    6.如果上述方法都没有解决问题,可以使用base64编码转换byte[]到base64字符串,再插入到数据库