@@ -592,29 +592,65 @@ private static Long findSchema(Connection connection, Position targetPosition, L
592592 } else {
593593 // Only consider binlog positions before the target position on the current server.
594594 // Within those, sort for the latest binlog file, then the latest binlog position.
595- String sql = "SELECT id from `schemas` "
596- + "WHERE deleted = 0 "
597- + "AND last_heartbeat_read <= ? AND ("
598- + "(binlog_file < ?) OR "
599- + "(binlog_file = ? and binlog_position < ? and base_schema_id is not null) OR "
600- + "(binlog_file = ? and binlog_position <= ? and base_schema_id is null) "
601- + ") AND server_id = ? "
602- + "ORDER BY last_heartbeat_read DESC, binlog_file DESC, binlog_position DESC limit 1" ;
603- try ( PreparedStatement s = connection .prepareStatement (sql ) ) {
604-
605- s .setLong (1 , targetPosition .getLastHeartbeatRead ());
606- s .setString (2 , targetBinlogPosition .getFile ());
607- s .setString (3 , targetBinlogPosition .getFile ());
608- s .setLong (4 , targetBinlogPosition .getOffset ());
609- s .setString (5 , targetBinlogPosition .getFile ());
610- s .setLong (6 , targetBinlogPosition .getOffset ());
611- s .setLong (7 , serverID );
612-
613- try ( ResultSet rs = s .executeQuery () ) {
614- if (rs .next ()) {
615- return rs .getLong ("id" );
616- } else
617- return null ;
595+ //
596+ // Binlog file names contain a numeric suffix (e.g. "mysql-bin-changelog.1215501").
597+ // When that suffix is parseable, we compare and sort numerically via CAST to avoid
598+ // lexicographic ordering bugs where a shorter number string like "122046" compares
599+ // greater than a longer one like "1215501". If the suffix cannot be parsed we fall
600+ // back to string comparison so that non-standard formats still work.
601+ Long targetFileNumber = targetBinlogPosition .getFileNumber ();
602+ if ( targetFileNumber != null ) {
603+ String sql = "SELECT id from `schemas` "
604+ + "WHERE deleted = 0 "
605+ + "AND last_heartbeat_read <= ? AND ("
606+ + "(CAST(SUBSTRING_INDEX(binlog_file, '.', -1) AS UNSIGNED) < ?) OR "
607+ + "(binlog_file = ? and binlog_position < ? and base_schema_id is not null) OR "
608+ + "(binlog_file = ? and binlog_position <= ? and base_schema_id is null) "
609+ + ") AND server_id = ? "
610+ + "ORDER BY last_heartbeat_read DESC, "
611+ + "CAST(SUBSTRING_INDEX(binlog_file, '.', -1) AS UNSIGNED) DESC, "
612+ + "binlog_position DESC limit 1" ;
613+ try ( PreparedStatement s = connection .prepareStatement (sql ) ) {
614+ s .setLong (1 , targetPosition .getLastHeartbeatRead ());
615+ s .setLong (2 , targetFileNumber );
616+ s .setString (3 , targetBinlogPosition .getFile ());
617+ s .setLong (4 , targetBinlogPosition .getOffset ());
618+ s .setString (5 , targetBinlogPosition .getFile ());
619+ s .setLong (6 , targetBinlogPosition .getOffset ());
620+ s .setLong (7 , serverID );
621+
622+ try ( ResultSet rs = s .executeQuery () ) {
623+ if (rs .next ()) {
624+ return rs .getLong ("id" );
625+ } else
626+ return null ;
627+ }
628+ }
629+ } else {
630+ // Fallback: file name has no parseable numeric suffix; use string comparison.
631+ String sql = "SELECT id from `schemas` "
632+ + "WHERE deleted = 0 "
633+ + "AND last_heartbeat_read <= ? AND ("
634+ + "(binlog_file < ?) OR "
635+ + "(binlog_file = ? and binlog_position < ? and base_schema_id is not null) OR "
636+ + "(binlog_file = ? and binlog_position <= ? and base_schema_id is null) "
637+ + ") AND server_id = ? "
638+ + "ORDER BY last_heartbeat_read DESC, binlog_file DESC, binlog_position DESC limit 1" ;
639+ try ( PreparedStatement s = connection .prepareStatement (sql ) ) {
640+ s .setLong (1 , targetPosition .getLastHeartbeatRead ());
641+ s .setString (2 , targetBinlogPosition .getFile ());
642+ s .setString (3 , targetBinlogPosition .getFile ());
643+ s .setLong (4 , targetBinlogPosition .getOffset ());
644+ s .setString (5 , targetBinlogPosition .getFile ());
645+ s .setLong (6 , targetBinlogPosition .getOffset ());
646+ s .setLong (7 , serverID );
647+
648+ try ( ResultSet rs = s .executeQuery () ) {
649+ if (rs .next ()) {
650+ return rs .getLong ("id" );
651+ } else
652+ return null ;
653+ }
618654 }
619655 }
620656 }
0 commit comments