From 3408f3ab47f3cd8d9818833f8327ed9727827bc8 Mon Sep 17 00:00:00 2001 From: Corey Winkelmann Date: Mon, 11 Nov 2024 16:45:24 -0700 Subject: [PATCH] refactor(mysql-status): Refined compatibility checks for MySQL and MariaDB versions --- .../zendesk/maxwell/MaxwellMysqlStatus.java | 96 ++++++++++++------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/zendesk/maxwell/MaxwellMysqlStatus.java b/src/main/java/com/zendesk/maxwell/MaxwellMysqlStatus.java index bed51c2c0..7d6498c27 100644 --- a/src/main/java/com/zendesk/maxwell/MaxwellMysqlStatus.java +++ b/src/main/java/com/zendesk/maxwell/MaxwellMysqlStatus.java @@ -25,36 +25,64 @@ public MaxwellMysqlStatus(Connection c) { private String sqlStatement(String variableName) { return "SHOW VARIABLES LIKE '" + variableName + "'"; } + public boolean isMaria() { try { DatabaseMetaData md = connection.getMetaData(); return md.getDatabaseProductVersion().toLowerCase().contains("mariadb"); - } catch ( SQLException e ) { + } catch (SQLException e) { return false; } } + /** + * Generates the appropriate SQL command to retrieve binary log status based on + * the database type and version. + * + * This method checks the database product name and version to determine + * the most suitable SQL command for retrieving binary log status information. + * It supports MySQL and MariaDB, with compatibility for recent version + * requirements: + * + * If an error occurs during metadata retrieval, the method defaults to "SHOW + * MASTER STATUS". + * + * @return a SQL command string to check binary log status + */ public String getShowBinlogSQL() { try { - DatabaseMetaData md = connection.getMetaData(); - if ( md.getDatabaseMajorVersion() >= 8 ) { + DatabaseMetaData metaData = connection.getMetaData(); + + String productName = metaData.getDatabaseProductName(); + + int majorVersion = metaData.getDatabaseMajorVersion(); + int minorVersion = metaData.getDatabaseMinorVersion(); + + boolean isMySQL = "MySQL".equalsIgnoreCase(productName); + boolean isMariaDB = "MariaDB".equalsIgnoreCase(productName); + + if (isMySQL && (majorVersion > 8 || (majorVersion == 8 && minorVersion >= 2))) { return "SHOW BINARY LOG STATUS"; + } else if (isMariaDB && (majorVersion > 10 || (majorVersion == 10 && minorVersion >= 5))) { + return "SHOW BINLOG STATUS"; } - } catch ( SQLException e ) { + } catch (SQLException e) { } return "SHOW MASTER STATUS"; } - - - - public String getVariableState(String variableName, boolean throwOnMissing) throws SQLException, MaxwellCompatibilityError { - try ( Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(sqlStatement(variableName)) ) { + public String getVariableState(String variableName, boolean throwOnMissing) + throws SQLException, MaxwellCompatibilityError { + try (Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(sqlStatement(variableName))) { String status; - if(!rs.next()) { - if ( throwOnMissing ) { + if (!rs.next()) { + if (throwOnMissing) { throw new MaxwellCompatibilityError("Could not check state for Mysql variable: " + variableName); } else { return null; @@ -65,35 +93,35 @@ public String getVariableState(String variableName, boolean throwOnMissing) thro return status; } } + public String getVariableState(String variableName) throws SQLException { try { return getVariableState(variableName, false); - } catch ( MaxwellCompatibilityError e ) { + } catch (MaxwellCompatibilityError e) { return null; } } - private void ensureVariableState(String variable, String state) throws SQLException, MaxwellCompatibilityError - { + private void ensureVariableState(String variable, String state) throws SQLException, MaxwellCompatibilityError { if (!getVariableState(variable, true).equals(state)) { throw new MaxwellCompatibilityError("variable " + variable + " must be set to '" + state + "'"); } } - private void ensureServerIDIsSet() throws SQLException, MaxwellCompatibilityError { String id = getVariableState("server_id", false); - if ( "0".equals(id) ) { - throw new MaxwellCompatibilityError("server_id is '0'. Maxwell will not function without a server_id being set."); + if ("0".equals(id)) { + throw new MaxwellCompatibilityError( + "server_id is '0'. Maxwell will not function without a server_id being set."); } } private void ensureRowImageFormat() throws SQLException, MaxwellCompatibilityError { String rowImageFormat = getVariableState("binlog_row_image", false); - if ( rowImageFormat == null ) // only present in mysql 5.6+ + if (rowImageFormat == null) // only present in mysql 5.6+ return; - if ( rowImageFormat.equals("MINIMAL") ) { + if (rowImageFormat.equals("MINIMAL")) { LOGGER.warn("Warning: binlog_row_image is set to MINIMAL. This may not be what you want."); LOGGER.warn("See http://maxwells-daemon.io/compat for more information."); } @@ -103,13 +131,14 @@ private void ensureRowImageFormat() throws SQLException, MaxwellCompatibilityErr * Verify that replication is in the expected state: * *
    - *
  1. Check that a serverID is set
  2. - *
  3. check that binary logging is on
  4. - *
  5. Check that the binlog_format is "ROW"
  6. - *
  7. Warn if binlog_row_image is MINIMAL
  8. + *
  9. Check that a serverID is set
  10. + *
  11. check that binary logging is on
  12. + *
  13. Check that the binlog_format is "ROW"
  14. + *
  15. Warn if binlog_row_image is MINIMAL
  16. *
+ * * @param c a JDBC connection - * @throws SQLException if the database has issues + * @throws SQLException if the database has issues * @throws MaxwellCompatibilityError if we are not in the expected state */ public static void ensureReplicationMysqlState(Connection c) throws SQLException, MaxwellCompatibilityError { @@ -123,8 +152,9 @@ public static void ensureReplicationMysqlState(Connection c) throws SQLException /** * Verify that the maxwell database is in the expected state + * * @param c a JDBC connection - * @throws SQLException if we have database issues + * @throws SQLException if we have database issues * @throws MaxwellCompatibilityError if we're not in the expected state */ public static void ensureMaxwellMysqlState(Connection c) throws SQLException, MaxwellCompatibilityError { @@ -135,14 +165,15 @@ public static void ensureMaxwellMysqlState(Connection c) throws SQLException, Ma /** * Verify that we can safely turn on maxwell GTID mode + * * @param c a JDBC connection - * @throws SQLException if we have db troubles + * @throws SQLException if we have db troubles * @throws MaxwellCompatibilityError if we're not in the expected state */ public static void ensureGtidMysqlState(Connection c) throws SQLException, MaxwellCompatibilityError { MaxwellMysqlStatus m = new MaxwellMysqlStatus(c); - if ( m.isMaria() ) + if (m.isMaria()) return; m.ensureVariableState("gtid_mode", "ON"); @@ -157,20 +188,21 @@ public static boolean isMaria(Connection c) { /** * Return an enum representing the current case sensitivity of the server + * * @param c a JDBC connection * @return case sensitivity * @throws SQLException if we have db troubles */ public static CaseSensitivity captureCaseSensitivity(Connection c) throws SQLException { final int value; - try ( Statement stmt = c.createStatement(); - ResultSet rs = stmt.executeQuery("select @@lower_case_table_names") ) { - if ( !rs.next() ) + try (Statement stmt = c.createStatement(); + ResultSet rs = stmt.executeQuery("select @@lower_case_table_names")) { + if (!rs.next()) throw new RuntimeException("Could not retrieve @@lower_case_table_names!"); value = rs.getInt(1); } - switch(value) { + switch (value) { case 0: return CaseSensitivity.CASE_SENSITIVE; case 1: