Talk about maxwell's MysqlPositionStore

Keywords: Programming Java SQL

order

This paper mainly studies MysqlPositionStore of maxwell

MysqlPositionStore

maxwell-1.25.1/src/main/java/com/zendesk/maxwell/schema/MysqlPositionStore.java

public class MysqlPositionStore {
	static final Logger LOGGER = LoggerFactory.getLogger(MysqlPositionStore.class);
	private static final Long DEFAULT_GTID_SERVER_ID = new Long(0);
	private final Long serverID;
	private String clientID;
	private final boolean gtidMode;
	private final ConnectionPool connectionPool;

	public MysqlPositionStore(ConnectionPool pool, Long serverID, String clientID, boolean gtidMode) {
		this.connectionPool = pool;
		this.clientID = clientID;
		this.gtidMode = gtidMode;
		if (gtidMode) {
			// we don't use server id for position store in gtid mode
			this.serverID = DEFAULT_GTID_SERVER_ID;
		} else {
			this.serverID = serverID;
		}
	}

	public void set(Position newPosition) throws SQLException, DuplicateProcessException {
		if ( newPosition == null )
			return;

		Long heartbeat = newPosition.getLastHeartbeatRead();

		String sql = "INSERT INTO `positions` set "
				+ "server_id = ?, "
				+ "gtid_set = ?, "
				+ "binlog_file = ?, "
				+ "binlog_position = ?, "
				+ "last_heartbeat_read = ?, "
				+ "client_id = ? "
				+ "ON DUPLICATE KEY UPDATE "
				+ "last_heartbeat_read = ?, "
				+ "gtid_set = ?, binlog_file = ?, binlog_position=?";

		BinlogPosition binlogPosition = newPosition.getBinlogPosition();
		connectionPool.withSQLRetry(1, (c) -> {
			PreparedStatement s = c.prepareStatement(sql);

			LOGGER.debug("Writing binlog position to " + c.getCatalog() + ".positions: " + newPosition + ", last heartbeat read: " + heartbeat);
			s.setLong(1, serverID);
			s.setString(2, binlogPosition.getGtidSetStr());
			s.setString(3, binlogPosition.getFile());
			s.setLong(4, binlogPosition.getOffset());
			s.setLong(5, heartbeat);
			s.setString(6, clientID);
			s.setLong(7, heartbeat);
			s.setString(8, binlogPosition.getGtidSetStr());
			s.setString(9, binlogPosition.getFile());
			s.setLong(10, binlogPosition.getOffset());

			s.execute();
		});
	}

	public Position get() throws SQLException {
		try ( Connection c = connectionPool.getConnection() ) {
			PreparedStatement s = c.prepareStatement("SELECT * from `positions` where server_id = ? and client_id = ?");
			s.setLong(1, serverID);
			s.setString(2, clientID);

			return positionFromResultSet(s.executeQuery());
		}
	}

	//......

}	
  • MysqlPositionStore provides set and get methods, in which the set method insert s a record into the positions table, and the get method takes the position records of the specified server ID and client ID from the positions table, where the set method uses connectionpool.withsqlregistry to execute sql

ConnectionPool

maxwell-1.25.1/src/main/java/com/zendesk/maxwell/util/ConnectionPool.java

public interface ConnectionPool {
	@FunctionalInterface
	public interface RetryableSQLFunction<T> {
		void apply(T t) throws SQLException, NoSuchElementException, DuplicateProcessException;
	}

	Connection getConnection() throws SQLException;
	void release();

	void withSQLRetry(int nTries, RetryableSQLFunction<Connection> inner)
		throws SQLException, NoSuchElementException, DuplicateProcessException;
}
  • ConnectionPool defines RetryableSQLFunction, getConnection, release, with sqlretry

C3P0ConnectionPool

maxwell-1.25.1/src/main/java/com/zendesk/maxwell/util/C3P0ConnectionPool.java

public class C3P0ConnectionPool implements ConnectionPool {
	private final ComboPooledDataSource cpds;
	static final Logger LOGGER = LoggerFactory.getLogger(C3P0ConnectionPool.class);

	@Override
	public Connection getConnection() throws SQLException {
		return cpds.getConnection();
	}

	@Override
	public void release() {
		cpds.close();
	}

	public C3P0ConnectionPool(String url, String user, String password) {
		cpds = new ComboPooledDataSource();
		cpds.setJdbcUrl(url);
		cpds.setUser(user);
		cpds.setPassword(password);


		// the settings below are optional -- c3p0 can work with defaults
		cpds.setMinPoolSize(1);
		cpds.setMaxPoolSize(5);
	}

	@Override
	public void withSQLRetry(int nTries, RetryableSQLFunction<Connection> inner)
		throws SQLException, DuplicateProcessException, NoSuchElementException {
		try ( final Connection c = getConnection() ){
			inner.apply(c);
			return;
		} catch (SQLException e) {
			if ( nTries > 0 ) {
				LOGGER.error("got SQL Exception: {}, {}, retrying...",
					e.getLocalizedMessage(),
					e.getCause().getLocalizedMessage()
				);
				withSQLRetry(nTries - 1, inner);
			} else {
				throw(e);
			}
		}
	}
}
  • C3P0ConnectionPool implements the ConnectionPool interface, which uses retrieablesqlfunction to execute logic, then captures SQLException, and recursively executes with sqlretry (nTries - 1, inner) when nTries is greater than 0

Summary

MysqlPositionStore provides set and get methods, in which the set method insert s a record into the positions table, and the get method takes the position records of the specified server ID and client ID from the positions table, where the set method uses connectionpool.withsqlregistry to execute sql

doc

Posted by pcjeffmac on Mon, 04 May 2020 19:38:25 -0700