diff --git a/CHANGELOG.md b/CHANGELOG.md index 19b24b6c9..d125901ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,16 @@ ## Change log +### 9.0.4 (12/20/2023 - ) + ### 9.0.3 (12/12/2023 - 12/19/2023) * kafka: updated client to 3.6.1 -* db: tweaked all datetime related operations for virtual thread +* db: tweaked datetime related operations for virtual thread > use new date api if possible, mysql driver uses too many locks/sync for old Date/Timestamp impl - > it recommends to map MySQL column type: LocalDate -> DATE, LocalDateTime -> DATETIME, ZonedDateTime -> TIMESTAMP(6) + > it recommends to map MySQL column type: LocalDate -> DATE, LocalDateTime -> DATETIME(6), ZonedDateTime -> TIMESTAMP(6) > with Timestamp, in mysql console, it is easier to use "SET @@session.time_zone" to adjust datetime value displayed * mysql: updated mysql driver according to profiling result - > use "core.framework.mysql:mysql-connector-j:8.2.0-r1" + > use "core.framework.mysql:mysql-connector-j:8.2.0-r2" > simplified and tuned used code path ### 9.0.2 (12/7/2023 - 12/12/2023) diff --git a/core-ng/src/main/java/core/framework/internal/db/DatabaseImpl.java b/core-ng/src/main/java/core/framework/internal/db/DatabaseImpl.java index 71473569e..da4c4f2a7 100644 --- a/core-ng/src/main/java/core/framework/internal/db/DatabaseImpl.java +++ b/core-ng/src/main/java/core/framework/internal/db/DatabaseImpl.java @@ -1,7 +1,5 @@ package core.framework.internal.db; -import com.mysql.cj.conf.PropertyDefinitions; -import com.mysql.cj.conf.PropertyKey; import core.framework.db.CloudAuthProvider; import core.framework.db.Database; import core.framework.db.IsolationLevel; @@ -36,8 +34,8 @@ */ public final class DatabaseImpl implements Database { static { - // disable unnecessary mysql connection cleanup thread to reduce overhead - System.setProperty(PropertyDefinitions.SYSP_disableAbandonedConnectionCleanup, "true"); + // disable unnecessary mysql connection cleanup thread to reduce overhead, refer to PropertyDefinitions.SYSP_disableAbandonedConnectionCleanup + System.setProperty("com.mysql.cj.disableAbandonedConnectionCleanup", "true"); } public final Pool pool; @@ -109,37 +107,37 @@ Properties driverProperties(String url) { if (authProvider == null && password != null) properties.setProperty("password", password); if (url.startsWith("jdbc:mysql:")) { // refer to https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html - properties.setProperty(PropertyKey.connectTimeout.getKeyName(), String.valueOf(timeout.toMillis())); + properties.setProperty("connectTimeout", String.valueOf(timeout.toMillis())); // add 10s for socket timeout which is read timeout, as all queries have queryTimeout, MySQL will send "KILL QUERY" command to MySQL server // otherwise we will see socket timeout exception (com.mysql.cj.exceptions.StatementIsClosedException: No operations allowed after statement closed) // refer to com.mysql.cj.CancelQueryTaskImpl - properties.setProperty(PropertyKey.socketTimeout.getKeyName(), String.valueOf(timeout.toMillis() + 10_000)); + properties.setProperty("socketTimeout", String.valueOf(timeout.toMillis() + 10_000)); // refer to https://dev.mysql.com/doc/c-api/8.0/en/mysql-affected-rows.html // refer to https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-connection.html#cj-conn-prop_useAffectedRows // Don't set the CLIENT_FOUND_ROWS flag when connecting to the server (not JDBC-compliant, will break most applications that rely on "found" rows vs. "affected rows" for DML statements), // but does cause "correct" update counts from "INSERT ... ON DUPLICATE KEY UPDATE" statements to be returned by the server. - properties.setProperty(PropertyKey.useAffectedRows.getKeyName(), "true"); + properties.setProperty("useAffectedRows", "true"); // refer to com.mysql.cj.protocol.a.NativeProtocol.configureTimeZone, // force to UTC, generally on cloud it defaults to UTC, this setting is to make local match cloud - properties.setProperty(PropertyKey.connectionTimeZone.getKeyName(), "UTC"); - properties.setProperty(PropertyKey.rewriteBatchedStatements.getKeyName(), "true"); - properties.setProperty(PropertyKey.queryInterceptors.getKeyName(), MySQLQueryInterceptor.class.getName()); - properties.setProperty(PropertyKey.logger.getKeyName(), "Slf4JLogger"); - properties.setProperty(PropertyKey.cachePrepStmts.getKeyName(), "true"); + properties.setProperty("connectionTimeZone", "UTC"); + properties.setProperty("rewriteBatchedStatements", "true"); + properties.setProperty("queryInterceptors", MySQLQueryInterceptor.class.getName()); + properties.setProperty("logger", "Slf4JLogger"); + properties.setProperty("cachePrepStmts", "true"); int index = url.indexOf('?'); // mysql with ssl has overhead, usually we ensure security on arch level, e.g. gcloud sql proxy or firewall rule // with gcloud iam / clear_text_password plugin, ssl is required // refer to https://cloud.google.com/sql/docs/mysql/authentication if (authProvider != null) { - properties.setProperty(PropertyKey.sslMode.getKeyName(), PropertyDefinitions.SslMode.PREFERRED.name()); + properties.setProperty("sslMode", "PREFERRED"); properties.setProperty(CloudAuthProvider.Provider.CLOUD_AUTH, "true"); } else if (index == -1 || url.indexOf("sslMode=", index + 1) == -1) { - properties.setProperty(PropertyKey.sslMode.getKeyName(), PropertyDefinitions.SslMode.DISABLED.name()); + properties.setProperty("sslMode", "DISABLED"); } - // refer to https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-charsets.html + // refer to https://dev.mysql.com/doc/connector-j/en/connector-j-reference-charsets.html if (index == -1 || url.indexOf("characterEncoding=", index + 1) == -1) - properties.setProperty(PropertyKey.characterEncoding.getKeyName(), "utf-8"); + properties.setProperty("characterEncoding", "utf-8"); } else if (url.startsWith("jdbc:postgresql:")) { // refer to org.postgresql.PGProperty properties.setProperty("connectTimeout", String.valueOf(timeout.toSeconds()));