[BugFix](jdbc catalog) fix OOM when jdbc catalog querys large data from doris #18067
When using JDBC Catalog to query the Doris data, because Doris does not provide the cursor reading method (that is, fetchBatchSize is invalid), Doris will send the data to the client at one time, resulting in client OOM. The MySQL protocol provides a stream reading method. Doris can use this method to avoid OOM. The requirements of using the stream method are setting fetchbatchsize = Integer.MIN_VALUE and setting ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY
This commit is contained in:
@ -151,6 +151,7 @@ Status JdbcConnector::open(RuntimeState* state, bool read) {
|
||||
ctor_params.__set_driver_path(local_location);
|
||||
ctor_params.__set_batch_size(read ? state->batch_size() : 0);
|
||||
ctor_params.__set_op(read ? TJdbcOperation::READ : TJdbcOperation::WRITE);
|
||||
ctor_params.__set_table_type(_conn_param.table_type);
|
||||
|
||||
jbyteArray ctor_params_bytes;
|
||||
// Pushed frame will be popped when jni_frame goes out-of-scope.
|
||||
|
||||
@ -480,3 +480,13 @@ The transaction mechanism ensures the atomicity of data writing to JDBC External
|
||||
7. What to do with errors such as "CAUSED BY: SQLException OutOfMemoryError" when performing JDBC queries?
|
||||
|
||||
If you have set `useCursorFetch` for MySQL, you can increase the JVM memory limit by modifying the value of `jvm_max_heap_size` in be.conf. The current default value is 1024M.
|
||||
|
||||
8. When using JDBC to query MySQL large data volume, if the query can occasionally succeed, occasionally report the following errors, and all the MySQL connections are completely disconnected when the error occurs:
|
||||
|
||||
```
|
||||
ERROR 1105 (HY000): errCode = 2, detailMessage = [INTERNAL_ERROR]UdfRuntimeException: JDBC executor sql has error:
|
||||
CAUSED BY: CommunicationsException: Communications link failure
|
||||
The last packet successfully received from the server was 4,446 milliseconds ago. The last packet sent successfully to the server was 4,446 milliseconds ago.
|
||||
```
|
||||
|
||||
When the above phenomenon appears, it may be that mysql server's own memory or CPU resources are exhausted and the MySQL service is unavailable. You can try to increase the memory or CPU resources of MySQL Server.
|
||||
|
||||
@ -480,3 +480,14 @@ set enable_odbc_transcation = true;
|
||||
7. 在使用JDBC查询过程中时,如果出现"CAUSED BY: SQLException OutOfMemoryError" 类似的错误
|
||||
|
||||
如果MYSQL已经主动设置useCursorFetch,可以在be.conf中修改jvm_max_heap_size的值,尝试增大JVM的内存,目前默认值为1024M。
|
||||
|
||||
8. 使用JDBC查询MYSQL大数据量时,如果查询偶尔能够成功,偶尔会报如下错误,且出现该错误时MYSQL的连接被全部断开,无法连接到MYSQL SERVER,过段时间后mysql又恢复正常,但是之前的连接都没了:
|
||||
|
||||
```
|
||||
ERROR 1105 (HY000): errCode = 2, detailMessage = [INTERNAL_ERROR]UdfRuntimeException: JDBC executor sql has error:
|
||||
CAUSED BY: CommunicationsException: Communications link failure
|
||||
The last packet successfully received from the server was 4,446 milliseconds ago. The last packet sent successfully to the server was 4,446 milliseconds ago.
|
||||
```
|
||||
|
||||
出现上述现象时,可能是Mysql Server自身的内存或CPU资源被耗尽导致Mysql服务不可用,可以尝试增大Mysql Server的内存或CPU配置。
|
||||
|
||||
|
||||
@ -283,7 +283,7 @@ public class JdbcResource extends Resource {
|
||||
newJdbcUrl = checkAndSetJdbcBoolParam(newJdbcUrl, "useUnicode", "false", "true");
|
||||
newJdbcUrl = checkAndSetJdbcParam(newJdbcUrl, "characterEncoding", "utf-8");
|
||||
}
|
||||
if (dbType.equals(MYSQL) || dbType.equals(POSTGRESQL)) {
|
||||
if (dbType.equals(POSTGRESQL)) {
|
||||
newJdbcUrl = checkAndSetJdbcBoolParam(newJdbcUrl, "useCursorFetch", "false", "true");
|
||||
}
|
||||
return newJdbcUrl;
|
||||
|
||||
@ -19,6 +19,7 @@ package org.apache.doris.udf;
|
||||
|
||||
import org.apache.doris.thrift.TJdbcExecutorCtorParams;
|
||||
import org.apache.doris.thrift.TJdbcOperation;
|
||||
import org.apache.doris.thrift.TOdbcTableType;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.google.common.base.Preconditions;
|
||||
@ -77,7 +78,7 @@ public class JdbcExecutor {
|
||||
throw new InternalException(e.getMessage());
|
||||
}
|
||||
init(request.driver_path, request.statement, request.batch_size, request.jdbc_driver_class,
|
||||
request.jdbc_url, request.jdbc_user, request.jdbc_password, request.op);
|
||||
request.jdbc_url, request.jdbc_user, request.jdbc_password, request.op, request.table_type);
|
||||
}
|
||||
|
||||
public void close() throws Exception {
|
||||
@ -237,7 +238,7 @@ public class JdbcExecutor {
|
||||
}
|
||||
|
||||
private void init(String driverUrl, String sql, int batchSize, String driverClass, String jdbcUrl, String jdbcUser,
|
||||
String jdbcPassword, TJdbcOperation op) throws UdfRuntimeException {
|
||||
String jdbcPassword, TJdbcOperation op, TOdbcTableType tableType) throws UdfRuntimeException {
|
||||
try {
|
||||
ClassLoader parent = getClass().getClassLoader();
|
||||
ClassLoader classLoader = UdfUtils.getClassLoader(driverUrl, parent);
|
||||
@ -260,7 +261,11 @@ public class JdbcExecutor {
|
||||
conn.setAutoCommit(false);
|
||||
Preconditions.checkArgument(sql != null);
|
||||
stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
stmt.setFetchSize(batchSize);
|
||||
if (tableType == TOdbcTableType.MYSQL) {
|
||||
stmt.setFetchSize(Integer.MIN_VALUE);
|
||||
} else {
|
||||
stmt.setFetchSize(batchSize);
|
||||
}
|
||||
batchSizeNum = batchSize;
|
||||
} else {
|
||||
stmt = conn.createStatement();
|
||||
|
||||
@ -372,6 +372,17 @@ enum TJdbcOperation {
|
||||
WRITE
|
||||
}
|
||||
|
||||
enum TOdbcTableType {
|
||||
MYSQL,
|
||||
ORACLE,
|
||||
POSTGRESQL,
|
||||
SQLSERVER,
|
||||
REDIS,
|
||||
MONGODB,
|
||||
CLICKHOUSE,
|
||||
SAP_HANA
|
||||
}
|
||||
|
||||
struct TJdbcExecutorCtorParams {
|
||||
1: optional string statement
|
||||
|
||||
@ -393,6 +404,8 @@ struct TJdbcExecutorCtorParams {
|
||||
|
||||
// "/home/user/mysql-connector-java-5.1.47.jar"
|
||||
8: optional string driver_path
|
||||
|
||||
9: optional TOdbcTableType table_type
|
||||
}
|
||||
|
||||
struct TJavaUdfExecutorCtorParams {
|
||||
@ -573,17 +586,6 @@ enum TTableType {
|
||||
TEST_EXTERNAL_TABLE,
|
||||
}
|
||||
|
||||
enum TOdbcTableType {
|
||||
MYSQL,
|
||||
ORACLE,
|
||||
POSTGRESQL,
|
||||
SQLSERVER,
|
||||
REDIS,
|
||||
MONGODB,
|
||||
CLICKHOUSE,
|
||||
SAP_HANA
|
||||
}
|
||||
|
||||
enum TKeysType {
|
||||
PRIMARY_KEYS,
|
||||
DUP_KEYS,
|
||||
|
||||
Reference in New Issue
Block a user