Class LogMinerStreamingChangeEventSource

java.lang.Object
io.debezium.connector.oracle.logminer.LogMinerStreamingChangeEventSource
All Implemented Interfaces:
ChangeEventSource, StreamingChangeEventSource<OraclePartition,OracleOffsetContext>

public class LogMinerStreamingChangeEventSource extends Object implements StreamingChangeEventSource<OraclePartition,OracleOffsetContext>
A StreamingChangeEventSource based on Oracle's LogMiner utility. The event handler loop is executed in a separate executor.
  • Field Details

  • Constructor Details

  • Method Details

    • execute

      public void execute(ChangeEventSource.ChangeEventSourceContext context, OraclePartition partition, OracleOffsetContext offsetContext)
      This is the loop to get changes from LogMiner
      Specified by:
      execute in interface StreamingChangeEventSource<OraclePartition,OracleOffsetContext>
      Parameters:
      context - change event source context
    • logOnlineRedoLogSizes

      private void logOnlineRedoLogSizes(OracleConnectorConfig config) throws SQLException
      Throws:
      SQLException
    • computeStartScnForFirstMiningSession

      private void computeStartScnForFirstMiningSession(OracleOffsetContext offsetContext, Scn firstScn)
      Computes the start SCN for the first mining session. Normally, this would be the snapshot SCN, but if there were pending transactions at the time the snapshot was taken, we'd miss the events in those transactions that have an SCN smaller than the snapshot SCN.
      Parameters:
      offsetContext - the offset context
      firstScn - the oldest SCN still available in the REDO logs
    • captureSessionMemoryStatistics

      private void captureSessionMemoryStatistics(OracleConnection connection) throws SQLException
      Throws:
      SQLException
    • createProcessor

      private LogMinerEventProcessor createProcessor(ChangeEventSource.ChangeEventSourceContext context, OraclePartition partition, OracleOffsetContext offsetContext)
    • getFirstScnInLogs

      private Scn getFirstScnInLogs(OracleConnection connection) throws SQLException
      Gets the first system change number in both archive and redo logs.
      Parameters:
      connection - database connection, should not be null
      Returns:
      the oldest system change number
      Throws:
      SQLException - if a database exception occurred
      io.debezium.DebeziumException - if the oldest system change number cannot be found due to no logs available
    • initializeRedoLogsForMining

      private void initializeRedoLogsForMining(OracleConnection connection, boolean postEndMiningSession, Scn startScn) throws SQLException
      Throws:
      SQLException
    • getCurrentLogFileSequences

      private List<BigInteger> getCurrentLogFileSequences(List<LogFile> logFiles)
      Get the current log file sequences from the supplied list of log files.
      Parameters:
      logFiles - list of log files
      Returns:
      list of sequences for the logs that are marked "current" in the database.
    • getMaxArchiveLogScn

      private Scn getMaxArchiveLogScn(List<LogFile> logFiles)
      Get the maximum archive log SCN
      Parameters:
      logFiles - the current logs that are part of the mining session
      Returns:
      the maximum system change number from the archive logs
      Throws:
      io.debezium.DebeziumException - if no logs are provided or if the provided logs has no archive log types
    • buildDataDictionary

      private void buildDataDictionary(OracleConnection connection) throws SQLException
      Requests Oracle to build the data dictionary. During the build step, Oracle will perform an additional series of redo log switches. Additionally, this call may introduce a delay in delivering incremental changes since the dictionary will need to have statistics gathered, analyzed, and prepared by LogMiner before any redo entries can be mined. This should only be used in conjunction with the mining strategy OracleConnectorConfig.LogMiningStrategy.CATALOG_IN_REDO.
      Parameters:
      connection - database connection
      Throws:
      SQLException - if a database exception occurred
    • hasLogSwitchOccurred

      private boolean hasLogSwitchOccurred() throws SQLException
      Checks whether a database log switch has occurred and updates metrics if so.
      Returns:
      true if a log switch was detected, otherwise false
      Throws:
      SQLException - if a database exception occurred
    • updateRedoLogMetrics

      private void updateRedoLogMetrics() throws SQLException
      Updates the redo log names and statues in the streaming metrics.
      Throws:
      SQLException - if a database exception occurred
    • getCurrentRedoLogFiles

      private Set<String> getCurrentRedoLogFiles(OracleConnection connection) throws SQLException
      Get a list of all the CURRENT redo log file names. For Oracle RAC clusters, multiple filenames will be returned, one for each node that participates in the cluster.
      Parameters:
      connection - database connection, should not be null
      Returns:
      unique set of all current redo log file names, with full paths, never null
      Throws:
      SQLException - if a database exception occurred
    • getCurrentRedoLogSequences

      private List<BigInteger> getCurrentRedoLogSequences() throws SQLException
      Get the current redo log sequence(s). In an Oracle RAC environment, there are multiple current redo logs and therefore this method returns multiple values, each relating to a single RAC node in the Oracle cluster.
      Returns:
      list of sequence numbers
      Throws:
      SQLException - if a database exception occurred
    • pauseBetweenMiningSessions

      private void pauseBetweenMiningSessions() throws InterruptedException
      Throws:
      InterruptedException
    • setNlsSessionParameters

      private void setNlsSessionParameters(OracleConnection connection) throws SQLException
      Sets the NLS parameters for the mining session.
      Parameters:
      connection - database connection, should not be null
      Throws:
      SQLException - if a database exception occurred
    • getDatabaseSystemTime

      private OffsetDateTime getDatabaseSystemTime(OracleConnection connection) throws SQLException
      Get the database system time in the database system's time zone.
      Parameters:
      connection - database connection, should not be null
      Returns:
      the database system time
      Throws:
      SQLException - if a database exception occurred
    • startMiningSession

      public boolean startMiningSession(OracleConnection connection, Scn startScn, Scn endScn, int attempts) throws SQLException
      Starts a new Oracle LogMiner session. When this is called, LogMiner prepares all the necessary state for an upcoming LogMiner view query. If the mining statement defines using DDL tracking, the data dictionary will be mined as a part of this call to prepare DDL tracking state for the upcoming LogMiner view query.
      Parameters:
      connection - database connection, should not be null
      startScn - mining session's starting system change number (exclusive), should not be null
      endScn - mining session's ending system change number (inclusive), can be null
      attempts - the number of mining start attempts
      Returns:
      true if the session was started successfully, false if it should be retried
      Throws:
      SQLException - if mining session failed to start
    • endMiningSession

      public void endMiningSession(OracleConnection connection, OracleOffsetContext offsetContext) throws SQLException
      End the current Oracle LogMiner session, if one is in progress. If the current session does not have an active mining session, a log message is recorded and the method is a no-op.
      Parameters:
      connection - database connection, should not be null
      offsetContext - connector offset context, should not be null
      Throws:
      SQLException - if the current mining session cannot be ended gracefully
    • calculateEndScn

      private Scn calculateEndScn(OracleConnection connection, Scn startScn, Scn prevEndScn) throws SQLException
      Calculates the mining session's end system change number. This calculation is based upon a sliding window algorithm to where if the connector is falling behind, the mining session's end point will be calculated based on the batch size and either be increased up to the maximum batch size or reduced to as low as the minimum batch size. Additionally, this method calculates and maintains a sliding algorithm for the sleep time between the mining sessions, increasing the pause up to the maximum sleep time if the connector is not behind or is mining too quick and reducing the pause down to the mimum sleep time if the connector has fallen behind and needs to catch-up faster.
      Parameters:
      connection - database connection, should not be null
      startScn - upcoming mining session's starting change number, should not be null
      prevEndScn - last mining session's ending system change number, can be null
      Returns:
      the ending system change number to be used for the upcoming mining session, never null
      Throws:
      SQLException - if the current max system change number cannot be obtained from the database
    • checkDatabaseAndTableState

      private void checkDatabaseAndTableState(OracleConnection connection, String pdbName, OracleDatabaseSchema schema) throws SQLException
      Checks and validates the database's supplemental logging configuration as well as the lengths of the table and column names that are part of the database schema.
      Parameters:
      connection - database connection, should not be null
      pdbName - pluggable database name, can be null when not using pluggable databases
      schema - connector's database schema, should not be null
      Throws:
      SQLException - if a database exception occurred
    • checkTableColumnNameLengths

      private void checkTableColumnNameLengths(Table table)
      Examines the table and column names and logs a warning if any name exceeds MAXIMUM_NAME_LENGTH.
      Parameters:
      table - the table, should not be null
    • isDatabaseAllSupplementalLoggingEnabled

      private boolean isDatabaseAllSupplementalLoggingEnabled(OracleConnection connection) throws SQLException
      Returns whether the database is configured with ALL supplemental logging.
      Parameters:
      connection - database connection, must not be null
      Returns:
      true if all supplemental logging is enabled, false otherwise
      Throws:
      SQLException - if a database exception occurred
    • isDatabaseMinSupplementalLoggingEnabled

      private boolean isDatabaseMinSupplementalLoggingEnabled(OracleConnection connection) throws SQLException
      Returns whether the database is configured with MIN supplemental logging.
      Parameters:
      connection - database connection, must not be null
      Returns:
      true if min supplemental logging is enabled, false otherwise
      Throws:
      SQLException - if a database exception occurred
    • isTableAllColumnsSupplementalLoggingEnabled

      private boolean isTableAllColumnsSupplementalLoggingEnabled(OracleConnection connection, TableId tableId) throws SQLException
      Return whether the table is configured with ALL COLUMN supplemental logging.
      Parameters:
      connection - database connection, must not be null
      tableId - table identifier, must not be null
      Returns:
      true if all column supplemental logging is enabled, false otherwise
      Throws:
      SQLException - if a database exception occurred
    • resolveFlushStrategy

      private LogWriterFlushStrategy resolveFlushStrategy()
      Resolves the Oracle LGWR buffer flushing strategy.
      Returns:
      the strategy to be used to flush Oracle's LGWR process, never null.
    • waitForStartScnInArchiveLogs

      private boolean waitForStartScnInArchiveLogs(ChangeEventSource.ChangeEventSourceContext context, Scn startScn) throws SQLException, InterruptedException
      Waits for the starting system change number to exist in the archive logs before returning.
      Parameters:
      context - the change event source context
      startScn - the starting system change number
      Returns:
      true if the code should continue, false if the code should end.
      Throws:
      SQLException - if a database exception occurred
      InterruptedException - if the pause between checks is interrupted
    • isStartScnInArchiveLogs

      private boolean isStartScnInArchiveLogs(Scn startScn) throws SQLException
      Returns whether the starting system change number is in the archive logs.
      Parameters:
      startScn - the starting system change number
      Returns:
      true if the starting system change number is in the archive logs; false otherwise.
      Throws:
      SQLException - if a database exception occurred
    • commitOffset

      public void commitOffset(Map<String,?> partition, Map<String,?> offset)
      Specified by:
      commitOffset in interface StreamingChangeEventSource<OraclePartition,OracleOffsetContext>