首批通过分布式安全可靠测评,为关键业务系统打造
如何查看 OceanBase 的 Batch 执行是否生效
更新时间:2026-05-28 02:06
最常用的方法就是通过 gv$sql_audit 来观察 Batch 执行是否生效,以下分几种场景举例:
Batch INSERT
如果开启了 rewriteBatchedStatements,那么在 PrepareStatement 对象中,JDBC 驱动会对 Batch INSERT 的 SQL 文本做特殊处理,INSERT 被改写成一条包含多个 VALUES 的单语句文本。
根据如下 JDBC 代码片段:
conn = DriverManager.getConnection(obUrl);
conn.setAutoCommit(false);
String SQL = "INSERT INTO TEST1 (C1, C2) VALUES (?, ?)";
PreparedStatemen pstmt = conn.prepareStatement(SQL);
int rowCount = 5, batchCount = 2;
for (int k=1; k<=batchCount; k++) {
for (int i=1; i<=rowCount; i++) {
pstmt.setInt(1, (k*100+i));
pstmt.setString(2, "test value");
pstmt.addBatch();
}
int[] count = pstmt.executeBatch();
pstmt.clearBatch();
}
conn.commit();
pstmt.close();
如果使用 Client 端 Prepared 语句,在 gv$sql_audit 中应该可以看到如下记录:
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (101, 'test value'), (102, 'test value'), (103, 'test value'), (104, 'test value'), (105, 'test value')
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (201, 'test value'), (202, 'test value'), (203, 'test value'), (204, 'test value'), (205, 'test value')
如果使用 Server 端 Prepared 语句,在 gv$sql_audit 中应该可以看到如下记录:
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (?, ?);
REQUEST_TYPE: 5
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (?, ?), (?, ?), (?, ?), (?, ?), (?, ?);
REQUEST_TYPE: 5
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (?, ?), (?, ?), (?, ?), (?, ?), (?, ?);
REQUEST_TYPE: 6
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (?, ?), (?, ?), (?, ?), (?, ?), (?, ?);
REQUEST_TYPE: 5
QUERY_SQL: INSERT INTO TEST1 (C1, C2) VALUES (?, ?), (?, ?), (?, ?), (?, ?), (?, ?);
REQUEST_TYPE: 6
需要注意的是,如果看到 prepare 语句(request_type=5)和 execute 语句(request_type=6)交替出现,那说明设置了缓存 Prepared 语句(cachePrepStmts),但是由于缓存不足而没有缓存住,这个时候通常需要调整缓存配置属性(prepStmtCacheSize,prepStmtCacheSqlLimit,maxBatchTotalParamsNum)。
Batch UPDATE
和 Batch INSERT 不同,JDBC 驱动无法对 Batch UPDATE 作改写变成单条语句。但如果开启了 rewriteBatchedStatements 且使用文本协议进行通讯,那么 JDBC 驱动仍会用分号连接多个 UPDATE 语句,使之变成一个 Multi Queries,此时若 OBServer 开启了 ob_enable_batched_multi_statement,那么 OBServer 会对这些格式一致的多条 UPDATE 语句当成一条语句进行解析,并根据对应的参数和数据分布,生成 batch physical plan 以提高性能。
根据如下 JDBC 代码片段:
conn = DriverManager.getConnection(obUrl);
conn.setAutoCommit(false);
String SQL = "UPDATE TEST1 SET C2 = ? WHERE C1 = ?";
PreparedStatemen pstmt = conn.prepareStatement(SQL);
int rowCount = 5, batchCount = 2;
for (int k=1; k<=batchCount; k++) {
for (int i=1; i<=rowCount; i++) {
pstmt.setString(1, "test value");
pstmt.setInt(2, (k*100+i));
}
int[] count = pstmt.executeBatch();
pstmt.clearBatch();
}
conn.commit();
pstmt.close();
在 gv$sql_audit 中应该可以看到如下记录:
QUERY_SQL: UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 101;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 102;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 103;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 104;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 105
RET_CODE: 0
IS_BATCHED_MULTI_STMT: 1
QUERY_SQL: UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 201;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 202;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 203;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 204;UPDATE TEST1 SET C2 = 'test value' WHERE C1 = 205
RET_CODE: 0
IS_BATCHED_MULTI_STMT: 1
注意这里的关键是分号拼接的 UPDATE 语句, IS_BATCHED_MULTI_STMT=1 和 RET_CODE=0。 倘若发现 RET_CODE=-5787 的一条拼接后的 UPDATE 语句,以及各自独立的 UPDATE 语句,这些独立的 UPDATE 语句表现出如下两个现象:
- elapsed_time 是单调递增的值。
- execute_time 是上下区间稳定的差不多的值。
则表明处理 batch physical plan 失败,除了没有正确配置参数外,还有一个可能是:OceanBase V3.2 之前的版本需要 UPDATE 语句的谓语条件包含全部主键。在 OceanBase V3.2 版本中,UPDATE 语句的谓语条件可以不用包含全部主键,需要打开 _enable_dist_data_access_service 变量,并确保使用新 SQL 引擎 _enable_static_typing_engine=True。
倘若发现没有一条拼接后的 UPDATE 语句,都是各自独立的 UPDATE 语句,这些独立的 UPDATE 语句表现出如下现象:
- elapsed_time 和 execute_time 一样是上下区间稳定的差不多的值。
则表明 JDBC 驱动端传到 ObServer 的就不是拼接的 UPDATE 语句,需要检查 JDBC 的配置属性。或者 ObServer 端没有开启 ob_enable_batched_multi_statement。
适用版本
OceanBase 数据库 V1.x、V2.x、V3.x 版本。