Skip to content
/ aproxy Public

A high-performance MySQL protocol proxy that transparently translates MySQL client requests to PostgreSQL backend calls, enabling MySQL clients to access PostgreSQL databases without code modification.

License

Notifications You must be signed in to change notification settings

axfor/aproxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

37 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MySQL to PostgreSQL Proxy

A high-performance MySQL protocol proxy that transparently translates MySQL client requests to PostgreSQL backend calls, enabling MySQL clients to access PostgreSQL databases without code modification.

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        MySQL Clients                                β”‚
β”‚  (Any MySQL client, ORM, or application - no code changes needed)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚ MySQL Protocol (3306)
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         AProxy Layer                               β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  MySQL Protocol Handler (pkg/protocol/mysql)                 β”‚   β”‚
β”‚ β”‚  - Handshake & Authentication                                β”‚   β”‚
β”‚ β”‚  - COM_QUERY / COM_PREPARE / COM_STMT_EXECUTE                β”‚   β”‚
β”‚ β”‚  - ResultSet Encoding (Field Packets)                        β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                      β”‚                                             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  SQL Rewrite Engine (pkg/sqlrewrite) - Hybrid AST + String   β”‚   β”‚
β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚   β”‚
β”‚ β”‚  β”‚ 1. SQL Parser: MySQL SQL β†’ AST                       β”‚    β”‚   β”‚
β”‚ β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β”‚
β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚   β”‚
β”‚ β”‚  β”‚ 2. AST Visitor: Semantic transformations             β”‚    β”‚   β”‚
│ │  │    - Types: TINYINT→SMALLINT, DATETIME→TIMESTAMP     │    │   │
β”‚ β”‚  β”‚    - Functions: NOW()β†’CURRENT_TIMESTAMP, IFNULL()    β”‚    β”‚   β”‚
│ │  │    - Constraints: AUTO_INCREMENT→SERIAL, INDEX       │    │   │
β”‚ β”‚  β”‚    - Placeholders: ? β†’ $1, $2, $3...                 β”‚    β”‚   β”‚
β”‚ β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β”‚
β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚   β”‚
β”‚ β”‚  β”‚ 3. PG Generator: AST β†’ PostgreSQL SQL                β”‚    β”‚   β”‚
β”‚ β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β”‚
β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚   β”‚
β”‚ β”‚  β”‚ 4. Post-Process: Syntactic cleanup (String-level)    β”‚    β”‚   β”‚
β”‚ β”‚  β”‚    - Quotes: `id` β†’ "id"                             β”‚    β”‚   β”‚
β”‚ β”‚  β”‚    - LIMIT: LIMIT n,m β†’ LIMIT m OFFSET n             β”‚    β”‚   β”‚
β”‚ β”‚  β”‚    - Keywords: CURRENT_TIMESTAMP() β†’ CURRENT_TIMESTAMPβ”‚   β”‚   β”‚
β”‚ β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                      β”‚                                             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  Type Mapper (pkg/mapper)                                    β”‚   β”‚
β”‚ β”‚  - MySQL ↔ PostgreSQL data type conversion                   β”‚   β”‚
β”‚ β”‚  - Error code mapping (PostgreSQL β†’ MySQL Error Codes)       β”‚   β”‚
β”‚ β”‚  - SHOW/DESCRIBE command emulation                           β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                      β”‚                                             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  Session Manager (pkg/session)                               β”‚   β”‚
β”‚ β”‚  - Session state tracking                                    β”‚   β”‚
β”‚ β”‚  - Transaction control (BEGIN/COMMIT/ROLLBACK)               β”‚   β”‚
β”‚ β”‚  - Prepared statement caching                                β”‚   β”‚
β”‚ β”‚  - Session variable management                               β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                      β”‚                                             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  Schema Cache (pkg/schema) - Global Cache with Generics      β”‚   β”‚
β”‚ β”‚  - AUTO_INCREMENT column detection (database.table key)      β”‚   β”‚
β”‚ β”‚  - Generic sync.Map (zero type assertion overhead)           β”‚   β”‚
β”‚ β”‚  - TTL-based expiration (5min default, configurable)         β”‚   β”‚
β”‚ β”‚  - DDL auto-invalidation (CREATE/ALTER/DROP TABLE)           β”‚   β”‚
β”‚ β”‚  - 99% query reduction in concurrent scenarios               β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                      β”‚                                             β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚  Connection Pool (internal/pool)                             β”‚   β”‚
β”‚ β”‚  - pgx connection pool management                            β”‚   β”‚
β”‚ β”‚  - Session affinity / pooled mode                            β”‚   β”‚
β”‚ β”‚  - Health checks                                             β”‚   β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚ PostgreSQL Protocol (pgx)
                         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   PostgreSQL Database                               β”‚
β”‚  (Actual data storage and query execution)                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                         β”‚  Observability  β”‚
                         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                         β”‚ Prometheus      β”‚
                         β”‚ (metrics :9090) β”‚
                         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                         β”‚ Logging         β”‚
                         β”‚ (pkg/observ...) β”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Processing Flow

MySQL Client Request
      β”‚
      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Protocol β”‚  Parse MySQL Wire Protocol packets
β”‚   Parsing   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. SQL      β”‚  Hybrid AST + String Rewriting:
β”‚   Rewrite   β”‚  β‘  Parse to AST (SQL Parser)
β”‚             β”‚  β‘‘ Transform AST (Semantic: types, functions, constraints)
β”‚             β”‚  β‘’ Generate PostgreSQL SQL
β”‚             β”‚  β‘£ Post-process (Syntactic: quotes, keywords)
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Execute  β”‚  Execute PostgreSQL query via pgx driver
β”‚   Query     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Type     β”‚  PostgreSQL types β†’ MySQL types
│   Mapping   │  (BIGSERIAL→BIGINT, BOOLEAN→TINYINT, etc.)
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. Protocol β”‚  Encode as MySQL ResultSet format
β”‚   Encoding  β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
MySQL Client Receives Response

πŸ“Š Compatibility Overview

Category Support Test Coverage Status
SQL Syntax 70+ patterns 50 test cases (100% pass) βœ… Production Ready
MySQL Protocol Commands 8 core commands Integration tested βœ… Fully Compatible
Data Types 6 categories, 20+ types All types tested βœ… Auto Conversion (78% full support)
Functions 5 categories, 30+ functions All functions tested βœ… Auto Mapping (71% support)
Unsupported Features 28 MySQL-specific features Documented with alternatives ⚠️ See COMPATIBILITY.md

Overall Compatibility: Covers 90%+ common MySQL OLTP scenarios, suitable for most OLTP application migrations.

πŸ“ˆ Detailed Statistics

βœ… Supported SQL Scenarios (70+ patterns)

  • Basic DML: SELECT, INSERT, UPDATE, DELETE (4 types)
  • DDL Operations: CREATE/DROP TABLE, CREATE/DROP INDEX, ALTER TABLE, TRUNCATE (6 types)
  • Transaction Control: BEGIN, COMMIT, ROLLBACK, AUTOCOMMIT (4 types)
  • Query Features: JOIN (4 types), subqueries, GROUP BY, HAVING, ORDER BY, LIMIT, DISTINCT, UNION (8+ types)
  • Data Types: Integer (10 types), Float (3 types), String (6 types), Binary (4 types), DateTime (4 types), Special (3 types) = 30+ types
  • Functions: Date/Time (4), String (8), Math (8), Aggregate (6), Conditional (4) = 30+ functions
  • Others: Prepared statements, batch operations, NULL handling, index constraints, auto-detection of unsupported features (5+ types)

Subtotal: ~40 SQL syntax patterns and operations (with automatic detection of 26 unsupported features)

πŸ§ͺ Test Coverage (50 passing + 26 documented unsupported)

  • Integration Tests (Passing): 50 cases

    • basic (23 tests): Table operations, queries, transactions, data types, functions
    • mysql_compat (8 tests): MySQL protocol compatibility verification
    • mysql_specific (13 tests): FULLTEXT search, LastInsertID, MATCH AGAINST, etc.
    • student (6 tests): Business scenarios, concurrent transactions, complex queries
  • Unsupported Features (Documented): 26 cases

    • mysql_specific_syntax (10 tests): DELETE LIMIT, FORCE INDEX, PARTITION, etc.
    • mysql_specific_functions (12 tests): DATE_FORMAT, FOUND_ROWS, GET_LOCK, etc.
    • mysql_specific_types (4 tests): ENUM, SET, SPATIAL types, combined types

Test Pass Rate: 100% (50/50 supported features passed) Coverage: 90%+ of common OLTP scenarios

⚠️ Unsupported MySQL Features (28 patterns)

  • Syntax (9 patterns): DELETE/UPDATE LIMIT, STRAIGHT_JOIN, FORCE/USE/IGNORE INDEX, INSERT DELAYED, PARTITION syntax, VALUES() in UPDATE
  • Functions (13 patterns): FOUND_ROWS(), GET_LOCK(), RELEASE_LOCK(), IS_FREE_LOCK(), DATE_FORMAT(), STR_TO_DATE(), TIMESTAMPDIFF(), FORMAT(), ENCRYPT(), PASSWORD(), INET_ATON(), INET_NTOA(), LOAD_FILE()
  • Data Types (2 patterns): SET, GEOMETRY/SPATIAL types
  • Other (4 patterns): LOAD DATA INFILE, LOCK/UNLOCK TABLES, User variables (@var)

Key Benefits:

  • βœ… Automatic Detection: All 28 unsupported features are automatically detected and logged with actionable suggestions
  • βœ… Detailed Documentation: See COMPATIBILITY.md for complete compatibility matrix
  • βœ… Migration Guide: Each unsupported feature includes PostgreSQL alternative recommendations

🎯 Use Cases

βœ… Suitable for AProxy:

  • OLTP applications (Online Transaction Processing)
  • Applications primarily using CRUD operations
  • Applications using common SQL syntax
  • Fast migration from MySQL to PostgreSQL

❌ Not Suitable for AProxy:

  • Heavy use of stored procedures and triggers
  • Dependency on MySQL-specific features (FULLTEXT, SPATIAL)
  • Heavy use of MySQL-specific data types (ENUM, SET)

Features

  • βœ… Full MySQL Protocol Support: Handshake, authentication, queries, prepared statements, etc.
  • βœ… Automatic SQL Rewriting: Converts MySQL SQL to PostgreSQL-compatible syntax
  • βœ… Session Management: Complete session state tracking including variables, transactions, prepared statements
  • βœ… Global Schema Cache: Generic sync.Map-based cache with DDL auto-invalidation (99% query reduction)
  • βœ… Type Mapping: Automatic conversion between MySQL and PostgreSQL data types
  • βœ… Error Mapping: Maps PostgreSQL error codes to MySQL error codes
  • βœ… SHOW/DESCRIBE Emulation: Simulates MySQL metadata commands
  • βœ… Connection Pooling: Supports session affinity and pooled modes
  • βœ… MySQL CDC (Binlog): Stream PostgreSQL changes as MySQL binlog events to MySQL replication clients
  • βœ… Observability: Prometheus metrics, structured logging, health checks
  • βœ… High Performance: Target 10,000+ QPS, P99 latency < 50ms
  • βœ… Production Ready: Docker and Kubernetes deployment support

Quick Start

Prerequisites

  • Go 1.21+
  • PostgreSQL 12+
  • Make (optional)

Build

# Using Make
make build

# Or directly with Go
GOEXPERIMENT=greenteagc go build -o bin/aproxy ./cmd/aproxy

Configuration

Copy the example configuration file and modify as needed:

cp configs/config.yaml configs/config.yaml

Edit configs/config.yaml:

server:
  host: "0.0.0.0"
  port: 3306

postgres:
  host: "localhost"
  port: 5432
  database: "mydb"
  user: "postgres"
  password: "your-password"

Run

# Using Make
make run

# Or run directly
./bin/aproxy -config configs/config.yaml

Connect

Connect using any MySQL client:

# MySQL CLI
mysql -h 127.0.0.1 -P 3306 -u postgres -p

# Application
# Simply point your MySQL connection string to the proxy address

Docker Deployment

Build Image

make docker-build

Run Container

docker run -d \
  --name aproxy \
  -p 3306:3306 \
  -p 9090:9090 \
  -v $(pwd)/configs/config.yaml:/app/config.yaml \
  aproxy:latest

Kubernetes Deployment

kubectl apply -f deployments/kubernetes/deployment.yaml

Architecture

MySQL Clients β†’ MySQL Protocol β†’ Proxy β†’ PostgreSQL Protocol β†’ PostgreSQL

The proxy contains the following components:

  1. MySQL Protocol Handler: Handles MySQL protocol handshake, authentication, and commands
  2. Session Manager: Maintains client session state
  3. SQL Rewrite Engine: Hybrid AST + String architecture using SQL parser for semantic transformations and post-processing for syntactic cleanup
  4. Type Mapper: Converts between MySQL and PostgreSQL types
  5. Error Mapper: Maps PostgreSQL errors to MySQL error codes
  6. Schema Cache: Global cache for table schema information (AUTO_INCREMENT columns) with generic sync.Map and DDL auto-invalidation
  7. Connection Pool: Manages connections to PostgreSQL

For detailed architecture documentation, see DESIGN.md

SQL Rewriting

Rewriting Architecture

AProxy uses a hybrid AST + String post-processing architecture for maximum accuracy and compatibility:

  1. AST Level (Semantic): Type conversions, function mappings, constraint handling via SQL parser
  2. String Level (Syntactic): Quote conversion, keyword cleanup, formatting adjustments

This architecture ensures column names like tinyint_col or now_timestamp are handled correctly without unintended replacements.

For detailed analysis, see AST_VS_STRING_CONVERSION.md

Conversion Rules

The proxy automatically handles the following MySQL to PostgreSQL conversions:

MySQL PostgreSQL Level
`identifier` "identifier" String
? placeholders $1, $2, ... AST
AUTO_INCREMENT SERIAL / BIGSERIAL AST
INSERT ... ON DUPLICATE KEY UPDATE INSERT ... ON CONFLICT ... DO UPDATE AST
REPLACE INTO INSERT ... ON CONFLICT ... AST
NOW() CURRENT_TIMESTAMP AST
IFNULL(a, b) COALESCE(a, b) AST
IF(cond, a, b) CASE WHEN cond THEN a ELSE b END AST
GROUP_CONCAT() STRING_AGG() AST
LAST_INSERT_ID() lastval() String
LOCK IN SHARE MODE FOR SHARE String
LIMIT n, m LIMIT m OFFSET n String

Supported Commands

MySQL Protocol Commands

  • βœ… COM_QUERY (text protocol queries)
  • βœ… COM_PREPARE (prepare statements)
  • βœ… COM_STMT_EXECUTE (execute prepared statements)
  • βœ… COM_STMT_CLOSE (close prepared statements)
  • βœ… COM_FIELD_LIST (field list)
  • βœ… COM_PING (ping)
  • βœ… COM_QUIT (quit)
  • βœ… COM_INIT_DB (change database)

Metadata Commands

  • βœ… SHOW DATABASES
  • βœ… SHOW TABLES
  • βœ… SHOW COLUMNS
  • βœ… DESCRIBE/DESC
  • βœ… SET variables
  • βœ… USE database

SQL Syntax Support

DDL (Data Definition Language)

  • βœ… CREATE TABLE (supports AUTO_INCREMENT, PRIMARY KEY, UNIQUE, INDEX)
  • βœ… DROP TABLE
  • βœ… ALTER TABLE (basic operations)
  • βœ… CREATE INDEX
  • βœ… DROP INDEX

DML (Data Manipulation Language)

  • βœ… SELECT (supports WHERE, JOIN, GROUP BY, HAVING, ORDER BY, LIMIT)
  • βœ… INSERT (supports single and batch inserts)
  • βœ… UPDATE (supports WHERE conditions)
  • βœ… DELETE (supports WHERE conditions)
  • βœ… REPLACE INTO (converted to INSERT ... ON CONFLICT)
  • βœ… INSERT ... ON DUPLICATE KEY UPDATE (converted to ON CONFLICT)

Transaction Control

  • βœ… BEGIN / START TRANSACTION
  • βœ… COMMIT
  • βœ… ROLLBACK
  • βœ… AUTOCOMMIT settings
  • βœ… SET TRANSACTION ISOLATION LEVEL

Data Type Support

Integer Types (AST-level conversion):

  • βœ… TINYINT β†’ SMALLINT
  • βœ… TINYINT UNSIGNED β†’ SMALLINT
  • βœ… SMALLINT β†’ SMALLINT
  • βœ… SMALLINT UNSIGNED β†’ INTEGER
  • βœ… MEDIUMINT β†’ INTEGER
  • βœ… INT / INTEGER β†’ INTEGER
  • βœ… INT UNSIGNED β†’ BIGINT
  • βœ… BIGINT β†’ BIGINT
  • βœ… BIGINT UNSIGNED β†’ NUMERIC(20,0)
  • βœ… YEAR β†’ SMALLINT

Floating-Point Types:

  • βœ… FLOAT β†’ REAL
  • βœ… DOUBLE β†’ DOUBLE PRECISION (String-level)
  • βœ… DECIMAL(M,D) / NUMERIC(M,D) β†’ NUMERIC(M,D)

String Types:

  • βœ… CHAR(N) β†’ CHAR(N)
  • βœ… VARCHAR(N) β†’ VARCHAR(N)
  • βœ… TEXT β†’ TEXT
  • βœ… TINYTEXT β†’ TEXT (String-level)
  • βœ… MEDIUMTEXT β†’ TEXT (String-level)
  • βœ… LONGTEXT β†’ TEXT (String-level)

Binary Types (Hybrid AST + String):

  • βœ… BLOB β†’ BYTEA
  • βœ… TINYBLOB β†’ BYTEA (via BLOB)
  • βœ… MEDIUMBLOB β†’ BYTEA (via BLOB)
  • βœ… LONGBLOB β†’ BYTEA (via BLOB)

Date/Time Types (AST-level):

  • βœ… DATE β†’ DATE
  • βœ… TIME β†’ TIME
  • βœ… DATETIME β†’ TIMESTAMP
  • βœ… TIMESTAMP β†’ TIMESTAMP WITH TIME ZONE

Special Types:

  • βœ… JSON β†’ JSONB (String-level)
  • βœ… ENUM(...) β†’ VARCHAR(50) (AST-level)
  • βœ… BOOLEAN / TINYINT(1) β†’ BOOLEAN (AST-level)

Function Support

All function conversions are handled at AST level for semantic correctness.

Date/Time Functions:

  • βœ… NOW() β†’ CURRENT_TIMESTAMP
  • βœ… CURDATE() / CURRENT_DATE() β†’ CURRENT_DATE
  • βœ… CURTIME() / CURRENT_TIME() β†’ CURRENT_TIME
  • βœ… UNIX_TIMESTAMP() β†’ EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)

String Functions:

  • βœ… CONCAT(a, b, ...) β†’ CONCAT(a, b, ...)
  • βœ… CONCAT_WS(sep, a, b, ...) β†’ CONCAT_WS(sep, a, b, ...)
  • βœ… LENGTH(s) β†’ LENGTH(s)
  • βœ… CHAR_LENGTH(s) β†’ CHAR_LENGTH(s)
  • βœ… SUBSTRING(s, pos, len) β†’ SUBSTRING(s, pos, len)
  • βœ… UPPER(s) / LOWER(s) β†’ UPPER(s) / LOWER(s)
  • βœ… TRIM(s) / LTRIM(s) / RTRIM(s) β†’ TRIM(s) / LTRIM(s) / RTRIM(s)
  • βœ… REPLACE(s, from, to) β†’ REPLACE(s, from, to)

Math Functions:

  • βœ… ABS(n), CEIL(n), FLOOR(n), ROUND(n) β†’ Same
  • βœ… MOD(n, m) β†’ MOD(n, m)
  • βœ… POWER(n, m) / POW(n, m) β†’ POWER(n, m)
  • βœ… SQRT(n) β†’ SQRT(n)
  • βœ… RAND() β†’ RANDOM()

Aggregate Functions:

  • βœ… COUNT(*) / COUNT(col) β†’ Same
  • βœ… SUM(col), AVG(col), MAX(col), MIN(col) β†’ Same
  • βœ… GROUP_CONCAT(col) β†’ STRING_AGG(col::TEXT, ',')

Conditional Functions:

  • βœ… IF(cond, a, b) β†’ CASE WHEN cond THEN a ELSE b END
  • βœ… IFNULL(a, b) β†’ COALESCE(a, b)
  • βœ… NULLIF(a, b) β†’ NULLIF(a, b)
  • βœ… COALESCE(a, b, c, ...) β†’ Same

Query Features

  • βœ… INNER JOIN
  • βœ… LEFT JOIN / RIGHT JOIN
  • βœ… Subqueries (IN, EXISTS)
  • βœ… GROUP BY with HAVING
  • βœ… ORDER BY
  • βœ… LIMIT offset, count (auto-converted to LIMIT count OFFSET offset)
  • βœ… DISTINCT
  • βœ… UNION / UNION ALL

Other Features

  • βœ… Prepared Statements
  • βœ… Batch Operations
  • βœ… NULL value handling
  • βœ… Indexes and constraints (PRIMARY KEY, UNIQUE, INDEX)
  • βœ… LastInsertId() support (via RETURNING clause)

CDC (Change Data Capture)

AProxy supports streaming PostgreSQL changes as MySQL binlog events, enabling MySQL replication clients (like Canal, Debezium, go-mysql) to subscribe to PostgreSQL data changes.

CDC Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    MySQL Replication Clients                            β”‚
β”‚           (Canal / Debezium / go-mysql / Custom Clients)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚ MySQL Binlog Protocol (COM_BINLOG_DUMP)
                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         AProxy CDC Server                               β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚  Binlog Encoder (pkg/replication/binlog_encoder.go)                 β”‚ β”‚
β”‚ β”‚  - TableMapEvent encoding (column metadata)                         β”‚ β”‚
β”‚ β”‚  - RowsEvent encoding (INSERT/UPDATE/DELETE)                        β”‚ β”‚
β”‚ β”‚  - QueryEvent encoding (DDL/TRUNCATE)                               β”‚ β”‚
β”‚ β”‚  - GTIDEvent encoding (transaction tracking)                        β”‚ β”‚
β”‚ β”‚  - DECIMAL/TIME/DATETIME binary format encoding                     β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                      β”‚                                                   β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚  Replication Server (pkg/replication/server.go)                     β”‚ β”‚
β”‚ β”‚  - MySQL binlog protocol server                                     β”‚ β”‚
β”‚ β”‚  - Multi-client support (COM_BINLOG_DUMP)                           β”‚ β”‚
β”‚ β”‚  - GTID-based positioning                                           β”‚ β”‚
β”‚ β”‚  - Event broadcasting to all connected clients                      β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                      β”‚                                                   β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚  PG Streamer (pkg/replication/pg_streamer.go)                       β”‚ β”‚
β”‚ β”‚  - PostgreSQL logical replication (pglogrepl)                       β”‚ β”‚
β”‚ β”‚  - Automatic REPLICA IDENTITY FULL setting                          β”‚ β”‚
β”‚ β”‚  - LSN checkpoint persistence (atomic file writes)                  β”‚ β”‚
β”‚ β”‚  - Auto-reconnect with exponential backoff                          β”‚ β”‚
β”‚ β”‚  - TOAST unchanged column handling                                   β”‚ β”‚
β”‚ β”‚  - 30+ PostgreSQL type mappings                                     β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                      β”‚ PostgreSQL Logical Replication                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   PostgreSQL Database                                    β”‚
β”‚  - Logical replication slot (pgoutput plugin)                            β”‚
β”‚  - Publication for table filtering                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CDC Event Flow

PostgreSQL WAL Change
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. PG Streamer   β”‚  Receive logical replication message
β”‚    (pglogrepl)   β”‚  Parse: INSERT/UPDATE/DELETE/TRUNCATE
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. Type Convert  β”‚  PostgreSQL types β†’ MySQL types
│                  │  (int4→INT, text→VARCHAR, etc.)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Binlog Encode β”‚  Create MySQL binlog events:
β”‚                  β”‚  - GTIDEvent (transaction ID)
β”‚                  β”‚  - TableMapEvent (schema)
β”‚                  β”‚  - WriteRowsEvent / UpdateRowsEvent / DeleteRowsEvent
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Broadcast     β”‚  Send to all connected
β”‚                  β”‚  MySQL replication clients
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CDC Configuration

Add the following to configs/config.yaml:

cdc:
  enabled: true                              # Enable CDC server
  server_id: 1                               # MySQL server ID for replication

  # PostgreSQL connection for logical replication
  pg_host: "localhost"
  pg_port: 5432
  pg_database: "mydb"
  pg_user: "postgres"
  pg_password: "password"
  pg_slot_name: "aproxy_cdc"                 # Replication slot name
  pg_publication_name: "aproxy_pub"          # Publication name

  # Checkpoint persistence for crash recovery
  checkpoint_file: "./data/cdc_checkpoint.json"
  checkpoint_interval: 10s

  # Auto-reconnect on connection loss
  reconnect_enabled: true
  reconnect_max_retries: 0                   # 0 = unlimited
  reconnect_initial_wait: 1s
  reconnect_max_wait: 30s                    # Exponential backoff cap

  # Backpressure handling
  backpressure_timeout: 30m                  # Max wait when channel full

PostgreSQL Setup

-- 1. Create publication for tables you want to replicate
CREATE PUBLICATION aproxy_pub FOR ALL TABLES;

-- Or for specific tables:
CREATE PUBLICATION aproxy_pub FOR TABLE users, orders, products;

-- 2. Create replication slot (optional, AProxy creates automatically)
SELECT pg_create_logical_replication_slot('aproxy_cdc', 'pgoutput');

Usage with Canal

import "github.com/go-mysql-org/go-mysql/canal"

cfg := canal.NewDefaultConfig()
cfg.Addr = "127.0.0.1:3306"
cfg.User = "root"
cfg.Flavor = "mysql"

c, _ := canal.NewCanal(cfg)
c.SetEventHandler(&MyEventHandler{})
c.Run()

CDC Metrics

CDC exposes the following Prometheus metrics:

Metric Description
mysql_pg_proxy_cdc_events_total Total events by type (insert/update/delete/truncate)
mysql_pg_proxy_cdc_replication_lag_ms Current replication lag in milliseconds
mysql_pg_proxy_cdc_backpressure_total Backpressure events (channel full)
mysql_pg_proxy_cdc_connected_clients Connected binlog dump clients
mysql_pg_proxy_cdc_last_lsn Last processed PostgreSQL LSN
mysql_pg_proxy_cdc_reconnects_total PostgreSQL reconnection attempts
mysql_pg_proxy_cdc_events_dropped_total Events dropped due to timeout

Supported CDC Features

  • βœ… DML Events: INSERT, UPDATE, DELETE with full row data
  • βœ… DDL Events: TRUNCATE TABLE
  • βœ… GTID Support: Transaction tracking with MySQL GTID format
  • βœ… Multi-client: Multiple replication clients simultaneously
  • βœ… Crash Recovery: LSN checkpoint persistence
  • βœ… Auto-reconnect: Exponential backoff on connection loss
  • βœ… Type Mapping: 30+ PostgreSQL to MySQL type conversions
  • βœ… TOAST Handling: Unchanged large column support

Monitoring

Prometheus Metrics

The proxy exposes the following metrics at :9090/metrics:

  • mysql_pg_proxy_active_connections - Active connections
  • mysql_pg_proxy_total_queries - Total queries
  • mysql_pg_proxy_query_duration_seconds - Query latency histogram
  • mysql_pg_proxy_errors_total - Error counts
  • mysql_pg_proxy_pg_pool_size - PostgreSQL connection pool size

Health Checks

curl http://localhost:9090/health

Performance

Target performance metrics:

  • Throughput: 10,000+ QPS (per instance)
  • Latency: P99 < 50ms (excluding network)
  • Connections: 1,000+ concurrent connections
  • Memory: < 100MB base + ~1MB/connection

Testing

# Run all tests
make test

# Unit tests only
make test-unit

# Integration tests only
make test-integration

# Performance tests
make bench

Test Coverage Details

AProxy includes 69 integration test cases covering common MySQL syntax and operation scenarios.

πŸ“‹ Basic Functionality Tests (46 cases)

Basic Queries

  • SELECT 1
  • SELECT NOW()

Table Operations

  • Create table with AUTO_INCREMENT
  • Insert single row
  • Select inserted data
  • Update row
  • Delete row
  • Verify final count

Prepared Statements

  • Prepare and execute
  • Verify inserted data

Transactions

  • Commit transaction
  • Rollback transaction

Metadata Commands

  • SHOW DATABASES
  • SHOW TABLES

Data Type Tests

  • Integer types: Create table with integer types, Insert integer values, Select and verify integer values
  • Floating-point types: Create table with floating point types, Insert and verify floating point values
  • String types: Create table with string types, Insert and verify string values
  • Date/time types: Create table with datetime types, Insert and verify datetime values

Aggregate Functions

  • COUNT
  • SUM
  • AVG
  • MAX
  • MIN

JOIN Queries

  • INNER JOIN
  • LEFT JOIN

Subqueries

  • Subquery with IN
  • Subquery in SELECT

Grouping and Sorting

  • GROUP BY with aggregates
  • GROUP BY with HAVING
  • LIMIT only
  • LIMIT with OFFSET (MySQL syntax)

NULL Value Handling

  • Insert NULL values
  • Query NULL values
  • IFNULL function

Batch Operations

  • Batch insert
  • Batch update
  • Batch delete

Indexes and Constraints

  • Create table with indexes
  • Insert and query with indexes
  • Unique constraint violation

Concurrent Testing

  • Multiple concurrent queries
πŸŽ“ Student Management Scenario Tests (21 cases)

Table Management

  • Create student table
  • Insert 100 student records
  • Query student data
  • Update student data
  • Delete student data

Aggregation and Complex Queries

  • Aggregate query - statistics by grade
  • Complex query - combined conditions

Transaction Scenarios

  • Transaction commit - credit transfer
  • Transaction rollback - invalid transfer
  • Explicit transaction control - BEGIN/COMMIT
  • Explicit transaction control - BEGIN/ROLLBACK
  • START TRANSACTION syntax

Autocommit

  • Disable autocommit and manual commit
  • Enable autocommit

SQL Rewriting

  • Data type conversion
  • Function conversion (NOW(), CURDATE(), etc.)
  • LIMIT syntax conversion
  • Backtick conversion

Concurrent Scenarios

  • Concurrent transfers (10 concurrent transactions)

Complex Business Scenarios

  • Complex transaction - student course enrollment
  • JOIN query - student enrollment information
πŸ”„ MySQL Compatibility Tests (2 cases)
  • COMMIT transaction
  • ROLLBACK transaction

Unsupported MySQL Features

The following MySQL features are not supported in PostgreSQL or require rewriting:

🚫 Completely Unsupported Features

Storage Engine Related

  • MyISAM/InnoDB specific features
  • FULLTEXT indexes (use PostgreSQL full-text search instead)
  • SPATIAL indexes (use PostGIS instead)

Replication and High Availability

  • Binary Log β†’ βœ… Supported via CDC (PostgreSQL logical replication β†’ MySQL binlog)
  • GTID (Global Transaction ID) β†’ βœ… Supported via CDC
  • Master-Slave replication commands (CHANGE MASTER TO, START/STOP SLAVE)

Data Types

  • ENUM (use custom types or CHECK constraints)
  • SET (use arrays or many-to-many tables)
  • YEAR type (use INTEGER or DATE)
  • Integer display width like INT(11)
  • UNSIGNED modifier

Special Syntax

  • Stored procedure language (needs rewriting to PL/pgSQL)
  • Trigger syntax differences
  • Event Scheduler (use pg_cron)
  • User variables (@variables)
  • LOAD DATA INFILE (use COPY FROM)

Function Differences

  • DATE_FORMAT() (convert to TO_CHAR)
  • FOUND_ROWS()
  • GET_LOCK()/RELEASE_LOCK() (use pg_advisory_lock)

For a detailed list of unsupported features and alternatives, see PG_UNSUPPORTED_FEATURES.md

Known Limitations

Unsupportable Features

  1. Storage Engine Specific: MyISAM/InnoDB specific behaviors
  2. Replication: Binary logs, GTID βœ… Now supported via CDC; master-slave admin commands still unsupported
  3. MySQL-Specific Syntax: Some stored procedures, triggers, event syntax

Features Requiring Migration

  1. Stored Procedures: Need rewriting to PL/pgSQL
  2. Triggers: Need rewriting to PostgreSQL syntax
  3. Full-Text Search: Different syntax and functionality

For a detailed list of limitations, see DESIGN.md

Documentation

Configuration Options

Option Description Default
server.port MySQL listen port 3306
server.max_connections Max connections 1000
postgres.connection_mode Connection mode session_affinity
sql_rewrite.enabled Enable SQL rewrite true
schema_cache.enabled Enable global schema cache true
schema_cache.ttl Cache TTL 5m
schema_cache.max_entries Max cache entries 100000
schema_cache.invalidate_on_ddl Auto-invalidate on DDL true
cdc.enabled Enable CDC server false
cdc.checkpoint_file LSN checkpoint file ./data/cdc_checkpoint.json
cdc.reconnect_enabled Auto-reconnect on connection loss true
observability.log_level Log level info

For complete configuration options, see config.yaml

Contributing

Issues and Pull Requests are welcome!

License

Apache License 2.0 - See LICENSE file for details

Related Projects

About

A high-performance MySQL protocol proxy that transparently translates MySQL client requests to PostgreSQL backend calls, enabling MySQL clients to access PostgreSQL databases without code modification.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •