从 OceanBase 数据库 V4.2.2 版本、OBProxy V4.2.3 版本开始,OceanBase 数据库支持 MYSQL_SET_OPTION 协议命令来控制 Multi-Query 功能的开启与关闭。
详细说明
Multi-Query
Multi-Query 功能允许客户端在一个请求中发送多个 SQL 语句,通过分号(;)分隔。这有助于减少客户端与服务器之间的通信次数,提高批量操作的效率。 在 OceanBase 数据库中,要启用 Multi-Query 功能,通常需要在 JDBC URL 中设置以下参数:
rewriteBatchedStatements=true: 启用批量执行的关键参数,确保多个 SQL 语句能够被组合在一起发送。
allowMultiQueries=true: 允许在一条语句中使用分号(;)分割多个请求。
对于批量 INSERT 执行,在 rewriteBatchedStatements=true 时,无论是否设置 allowMutiQueries=true,JDBC 都会尝试调用 executeBatchedInserts 方法,将多条 INSERT 语句拼接为 INSERT ... VALUES (),(),()... 的形式。但是,如果每条 INSERT 语句的格式不完全相同,则无法拼接为一个 INSERT 带多个 VALUE 的语句,这时 JDBC 会尝试使用 executePreparedBatchAsMultiStatement 方法,即使用分号(;)拼接多条语句,而这就需要使用 Multi-Query 功能。
COM_SET_OPTION
在 MySQL 数据库中,有一个称为 COM_SET_OPTION 的客户端/服务器通信协议命令,用于在客户端和服务器之间设置特定选项。
C API
MYSQL_SET_OPTION 是 MySQL C API 的一部分,基于 COM_SET_OPTION 协议通过 mysql_options() 函数设置连接选项,其作用是在连接数据库前配置额外选项,比如开启 Multi-Query 功能。
C 程序的示例:
#include <mysql.h>
#include <stdio.h>
int main() {
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
// 初始化连接句柄
conn = mysql_init(NULL);
// 启用 multi-statements
mysql_options(conn, MYSQL_OPT_MULTI_STATEMENTS_ON, NULL);
// 连接到数据库(
mysql_real_connect(conn, "localhost", "root", "your_password", "test", 0, NULL, 0);
// 执行多语句 SQL(
mysql_query(conn, "SELECT 'Hello' AS msg; SELECT 'World' AS msg;");
mysql_close(conn);
return 0;
}
JDBC
虽然 JDBC 没有暴露 COM_SET_OPTION 这个命令的接口,但 MySQL 的 JDBC 驱动内部确实会使用 COM_SET_OPTION 协议命令来启用某些功能。比如,当 JDBC 连接字符串中设置 allowMultiQueries=true 时,在连接时 JDBC 内部会通过 COM_SET_OPTION 启用 CLIENT_MULTI_STATEMENTS 标志,从而允许执行 Multi-Query 语句。
JDBC 示例:
jdbc:mysql://x.x.x.x:port/dbname?rewriteBatchedStatements=true&allowMultiQueries=true
MySQL JDBC 内部调用 COM_SET_OPTION:

OceanBase 支持 COM_SET_OPTION 协议
如果初始连接未开启 Multi-Query 功能,而在后面使用 Batch 接口时,OceanBase JDBC 的早期版本以及社区版本均会通过 COM_SET_OPTION 命令开启 Multi-Query 状态。如果 OceanBase 数据库版本不兼容 COM_SET_OPTION 通信协议,则会出现问题。
示例: 客户使用 DataWorks 向 OceanBase 数据库导入数据,初始连接串中配置 rewriteBatchedStatements=true 和 allowMutiQueries=false,且设置了 BatchSize 来进行批量插入。但在使用时发现 Batch Insert 会被降级为单条记录的插入,而且有以下报错信息。
2022-12-02 16:05:15,534 [http-nio-8096-exec-6] WARN c.z.h.p.ProxyConnection:157 - HikariPool-1 - Connection com.mysql.cj.jdbc.ConnectionImpl@1df265f6 marked as broken because of SQLSTATE(0A000), ErrorCode(1235)
java.sql.SQLException: Not supported feature or function
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executePreparedBatchAsMultiStatement(ClientPreparedStatement.java:603)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchInternal(ClientPreparedStatement.java:431)
at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:796)
at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:128)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java)
at sun.reflect.GeneratedMethodAccessor673.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:78)
at com.sun.proxy.$Proxy317.executeBatch(Unknown Source)
at com.baomidou.mybatisplus.core.executor.MybatisBatchExecutor.doFlushStatements(MybatisBatchExecutor.java:133)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:129)
at org.apache.ibatis.executor.BaseExecutor.flushStatements(BaseExecutor.java:122)
at com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.flushStatements(MybatisCachingExecutor.java:216)
这个报错显示 JDBC 使用 executePreparedBatchAsMultiStatement 方法执行 Multi-Query,但数据库不支持该功能。为了解决这个问题,OceanBase 数据库从 V4.2.2 版本、OBProxy 从 V4.2.3 版本开始支持 COM_SET_OPTION 协议,目前仅支持设置 Multi-Query 功能开关。
| Option | Description |
|---|---|
| MYSQL_OPTION_MULTI_STATEMENTS_ON | Enable multiple-statement support |
| MYSQL_OPTION_MULTI_STATEMENTS_OFF | Disable multiple-statement support |
适用版本
OceanBase 数据库 V4.2.2 GA(oceanbase-4.2.2.0-100000082024011317)及之后版本。
OBProxy V4.2.3 及之后版本。