CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-flywaydb--flyway-mysql

MySQL database type plugin for Flyway database migration engine providing specialized MySQL and MariaDB support for schema migrations.

Pending
Overview
Eval results
Files

connection-management.mddocs/

Connection Management

Connection management classes handle MySQL-specific connection state, variable management, and AWS RDS detection. They ensure proper connection restoration and provide specialized functionality for MySQL environments.

Capabilities

MySQL Connection

MySQL-specific connection implementation with state management, variable restoration, and environment detection.

/**
 * MySQL-specific connection implementation
 * Handles connection state, user variables, and AWS RDS detection
 */
public class MySQLConnection extends Connection<MySQLDatabase> {
    
    /**
     * Creates a new MySQL connection instance
     * Initializes connection state and detects environment capabilities
     * @param database MySQL database instance
     * @param connection Raw JDBC connection
     */
    public MySQLConnection(MySQLDatabase database, java.sql.Connection connection);
    
    /**
     * Detects if connection is to AWS RDS
     * @return true if connected to AWS RDS MySQL instance
     */
    public boolean isAwsRds();
    
    /**
     * Restores original connection state on connection close
     * Resets user variables and restores system variables
     * @throws SQLException if restoration fails
     */
    @Override
    protected void doRestoreOriginalState() throws SQLException;
    
    /**
     * Gets current schema name (database name in MySQL)
     * @return Current database name or null if none selected
     * @throws SQLException if query fails
     */
    @Override
    protected String getCurrentSchemaNameOrSearchPath() throws SQLException;
    
    /**
     * Changes current schema (database) to specified name
     * @param schema Schema name to switch to, or null to clear
     * @throws SQLException if schema change fails
     */
    @Override
    public void doChangeCurrentSchemaOrSearchPathTo(String schema) throws SQLException;
    
    /**
     * Gets current schema object
     * @return MySQLSchema instance for current database, or null if none
     * @throws SQLException if query fails
     */
    @Override
    protected Schema doGetCurrentSchema() throws SQLException;
    
    /**
     * Gets schema object for specified name
     * @param name Schema (database) name
     * @return MySQLSchema instance
     */
    @Override
    public Schema getSchema(String name);
    
    /**
     * Executes callable with table lock protection
     * Uses named locks when available, otherwise falls back to superclass
     * @param <T> Return type
     * @param table Table to lock
     * @param callable Operation to execute with lock
     * @return Result from callable
     */
    @Override
    public <T> T lock(Table table, Callable<T> callable);
    
    /**
     * Determines if named lock template can be used
     * Based on database version and user permissions
     * @return true if named locks are available
     */
    protected boolean canUseNamedLockTemplate();
}

Constants and Fields:

// System table names for user variable queries
private static final String USER_VARIABLES_TABLE_MARIADB = "information_schema.user_variables";
private static final String USER_VARIABLES_TABLE_MYSQL = "performance_schema.user_variables_by_thread";
private static final String FOREIGN_KEY_CHECKS = "foreign_key_checks";
private static final String SQL_SAFE_UPDATES = "sql_safe_updates";

// Connection state fields
private final String userVariablesQuery;
private final boolean canResetUserVariables;
private final int originalForeignKeyChecks;
private final int originalSqlSafeUpdates;
private final boolean awsRds; // Accessible via isAwsRds() getter

Usage Examples:

// Connection is typically created by MySQLDatabase
MySQLDatabase database = new MySQLDatabase(config, jdbcFactory, interceptor);
MySQLConnection connection = database.getConnection();

// Check AWS RDS status
boolean isRds = connection.isAwsRds();
if (isRds) {
    // Handle RDS-specific behavior
    System.out.println("Connected to AWS RDS MySQL");
}

// Check named lock capability
boolean canUseLocks = connection.canUseNamedLockTemplate();
if (canUseLocks) {
    // Named locks are available for concurrent operations
}

Connection State Management

Variable Restoration

The connection automatically manages and restores MySQL system variables:

Foreign Key Checks:

  • Stores original foreign_key_checks value on connection
  • Restores original value when connection is closed

SQL Safe Updates:

  • Stores original sql_safe_updates value on connection
  • Restores original value when connection is closed

User Variable Management

For supported MySQL/MariaDB versions and permissions:

MySQL (5.7+):

  • Queries performance_schema.user_variables_by_thread
  • Resets user variables to clean state

MariaDB (10.2+):

  • Queries information_schema.user_variables
  • Resets user variables to clean state

Requirements:

  • Sufficient database version
  • SELECT permissions on system tables
  • User variable reset capability detection
// User variable reset capability is automatically detected
// and used when available during connection restoration

Environment Detection

AWS RDS Detection

The connection detects AWS RDS environments using multiple indicators:

Detection Methods:

  1. RDS admin user existence check
  2. Connection metadata analysis
  3. URL pattern matching (handled at database level)
// AWS RDS detection example
if (connection.isAwsRds()) {
    // AWS RDS specific handling:
    // - Different privilege model
    // - Specific feature limitations
    // - Different monitoring approaches
}

Version and Capability Detection

The connection performs capability detection during initialization:

User Variable Reset:

// Capability detection logic
if (database.isMariaDB() && !database.getVersion().isAtLeast("10.2")) {
    // User variable reset disabled for older MariaDB
}
if (!database.isMariaDB() && !database.getVersion().isAtLeast("5.7")) {
    // User variable reset disabled for older MySQL
}

Event Scheduler Access:

// Event scheduler queryability detection
boolean canQueryEvents = database.eventSchedulerQueryable;
if (canQueryEvents) {
    // Can query information_schema.events
} else {
    // Event scheduler is OFF or DISABLED (MariaDB)
}

Named Lock Support

Named locks provide coordination for concurrent Flyway operations:

Lock Template Usage

/**
 * Creates named lock template when supported
 * @param jdbcTemplate JDBC template for operations
 * @param discriminator Unique identifier for lock name
 * @return MySQLNamedLockTemplate instance
 */
MySQLNamedLockTemplate lockTemplate = new MySQLNamedLockTemplate(jdbcTemplate, discriminator);

// Execute with lock protection
Object result = lockTemplate.execute(() -> {
    // Critical section protected by named lock
    return performCriticalOperation();
});

Lock Requirements

Named locks are available when:

  • Database supports GET_LOCK() and RELEASE_LOCK() functions
  • Connection has necessary permissions
  • Not running in environments that restrict locking

Connection Properties and Configuration

Default Properties

Connections are configured with MySQL-specific properties:

// Set during connection establishment
props.put("connectionAttributes", "program_name:" + APPLICATION_NAME);

This helps identify Flyway connections in:

  • MySQL process list (SHOW PROCESSLIST)
  • Performance schema tables
  • Database monitoring systems

Connection Restoration

The connection implements automatic state restoration:

// Restoration happens automatically on connection close
@Override
protected void doRestoreOriginalState() throws SQLException {
    // Reset user variables (if supported)
    resetUserVariables();
    
    // Restore system variables
    jdbcTemplate.execute(
        "SET foreign_key_checks=?, sql_safe_updates=?",
        originalForeignKeyChecks,
        originalSqlSafeUpdates
    );
}

Error Handling and Diagnostics

Connection Diagnostics

The connection provides diagnostic information for troubleshooting:

Variable Access Issues:

// When user variable reset fails
LOG.debug("Disabled user variable reset as " + tableNamel + " cannot be queried " +
         "(SQL State: " + e.getSQLState() + ", Error Code: " + e.getErrorCode() + ")");

Version Compatibility:

// When features are disabled due to version
LOG.debug("Disabled user variable reset as it is only available from MySQL 5.7 onwards");
LOG.debug("Disabled user variable reset as it is only available from MariaDB 10.2 onwards");

Common Connection Issues

Permission Problems:

  • Cannot query performance_schema.user_variables_by_thread (MySQL)
  • Cannot query information_schema.user_variables (MariaDB)
  • Missing GET_LOCK()/RELEASE_LOCK() permissions

Version Issues:

  • MySQL versions below 5.7 have limited user variable support
  • MariaDB versions below 10.2 have limited user variable support
  • Different system table availability across versions

Environment Issues:

  • AWS RDS has different permission models
  • Some cloud environments restrict certain operations
  • Proxy connections may affect capability detection

Integration with Database Operations

The connection integrates with other database components:

Schema Operations:

MySQLSchema schema = connection.getSchema("myschema");
// Connection provides MySQL-specific schema behavior

Table Operations:

MySQLTable table = schema.getTable("mytable");
// Connection enables MySQL-specific table operations

Transaction Management:

// MySQL connections handle DDL auto-commit behavior
// No transaction support for DDL operations
boolean supportsDdl = connection.getDatabase().supportsDdlTransactions(); // false

Install with Tessl CLI

npx tessl i tessl/maven-org-flywaydb--flyway-mysql

docs

connection-management.md

database-operations.md

database-types.md

index.md

schema-management.md

sql-parsing.md

utility-components.md

tile.json