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.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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...) β
βββββββββββββββββββ
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
| 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 |
Overall Compatibility: Covers 90%+ common MySQL OLTP scenarios, suitable for most OLTP application migrations.
π Detailed Statistics
- 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)
-
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
- 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
β 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)
- β 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
- Go 1.21+
- PostgreSQL 12+
- Make (optional)
# Using Make
make build
# Or directly with Go
GOEXPERIMENT=greenteagc go build -o bin/aproxy ./cmd/aproxyCopy the example configuration file and modify as needed:
cp configs/config.yaml configs/config.yamlEdit configs/config.yaml:
server:
host: "0.0.0.0"
port: 3306
postgres:
host: "localhost"
port: 5432
database: "mydb"
user: "postgres"
password: "your-password"# Using Make
make run
# Or run directly
./bin/aproxy -config configs/config.yamlConnect 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 addressmake docker-builddocker run -d \
--name aproxy \
-p 3306:3306 \
-p 9090:9090 \
-v $(pwd)/configs/config.yaml:/app/config.yaml \
aproxy:latestkubectl apply -f deployments/kubernetes/deployment.yamlMySQL Clients β MySQL Protocol β Proxy β PostgreSQL Protocol β PostgreSQL
The proxy contains the following components:
- MySQL Protocol Handler: Handles MySQL protocol handshake, authentication, and commands
- Session Manager: Maintains client session state
- SQL Rewrite Engine: Hybrid AST + String architecture using SQL parser for semantic transformations and post-processing for syntactic cleanup
- Type Mapper: Converts between MySQL and PostgreSQL types
- Error Mapper: Maps PostgreSQL errors to MySQL error codes
- Schema Cache: Global cache for table schema information (AUTO_INCREMENT columns) with generic sync.Map and DDL auto-invalidation
- Connection Pool: Manages connections to PostgreSQL
For detailed architecture documentation, see DESIGN.md
AProxy uses a hybrid AST + String post-processing architecture for maximum accuracy and compatibility:
- AST Level (Semantic): Type conversions, function mappings, constraint handling via SQL parser
- 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
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 |
- β 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)
- β SHOW DATABASES
- β SHOW TABLES
- β SHOW COLUMNS
- β DESCRIBE/DESC
- β SET variables
- β USE database
- β CREATE TABLE (supports AUTO_INCREMENT, PRIMARY KEY, UNIQUE, INDEX)
- β DROP TABLE
- β ALTER TABLE (basic operations)
- β CREATE INDEX
- β DROP INDEX
- β 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)
- β BEGIN / START TRANSACTION
- β COMMIT
- β ROLLBACK
- β AUTOCOMMIT settings
- β SET TRANSACTION ISOLATION LEVEL
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)
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
- β 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
- β Prepared Statements
- β Batch Operations
- β NULL value handling
- β Indexes and constraints (PRIMARY KEY, UNIQUE, INDEX)
- β LastInsertId() support (via RETURNING clause)
AProxy supports streaming PostgreSQL changes as MySQL binlog events, enabling MySQL replication clients (like Canal, Debezium, go-mysql) to subscribe to PostgreSQL data changes.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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
ββββββββββββββββββββ
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-- 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');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 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 |
- β 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
The proxy exposes the following metrics at :9090/metrics:
mysql_pg_proxy_active_connections- Active connectionsmysql_pg_proxy_total_queries- Total queriesmysql_pg_proxy_query_duration_seconds- Query latency histogrammysql_pg_proxy_errors_total- Error countsmysql_pg_proxy_pg_pool_size- PostgreSQL connection pool size
curl http://localhost:9090/healthTarget performance metrics:
- Throughput: 10,000+ QPS (per instance)
- Latency: P99 < 50ms (excluding network)
- Connections: 1,000+ concurrent connections
- Memory: < 100MB base + ~1MB/connection
# Run all tests
make test
# Unit tests only
make test-unit
# Integration tests only
make test-integration
# Performance tests
make benchAProxy includes 69 integration test cases covering common MySQL syntax and operation scenarios.
π Basic Functionality Tests (46 cases)
- SELECT 1
- SELECT NOW()
- Create table with AUTO_INCREMENT
- Insert single row
- Select inserted data
- Update row
- Delete row
- Verify final count
- Prepare and execute
- Verify inserted data
- Commit transaction
- Rollback transaction
- SHOW DATABASES
- SHOW TABLES
- 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
- COUNT
- SUM
- AVG
- MAX
- MIN
- INNER JOIN
- LEFT JOIN
- Subquery with IN
- Subquery in SELECT
- GROUP BY with aggregates
- GROUP BY with HAVING
- LIMIT only
- LIMIT with OFFSET (MySQL syntax)
- Insert NULL values
- Query NULL values
- IFNULL function
- Batch insert
- Batch update
- Batch delete
- Create table with indexes
- Insert and query with indexes
- Unique constraint violation
- Multiple concurrent queries
π Student Management Scenario Tests (21 cases)
- Create student table
- Insert 100 student records
- Query student data
- Update student data
- Delete student data
- Aggregate query - statistics by grade
- Complex query - combined conditions
- Transaction commit - credit transfer
- Transaction rollback - invalid transfer
- Explicit transaction control - BEGIN/COMMIT
- Explicit transaction control - BEGIN/ROLLBACK
- START TRANSACTION syntax
- Disable autocommit and manual commit
- Enable autocommit
- Data type conversion
- Function conversion (NOW(), CURDATE(), etc.)
- LIMIT syntax conversion
- Backtick conversion
- Concurrent transfers (10 concurrent transactions)
- Complex transaction - student course enrollment
- JOIN query - student enrollment information
π MySQL Compatibility Tests (2 cases)
- COMMIT transaction
- ROLLBACK transaction
The following MySQL features are not supported in PostgreSQL or require rewriting:
π« Completely Unsupported Features
- MyISAM/InnoDB specific features
- FULLTEXT indexes (use PostgreSQL full-text search instead)
- SPATIAL indexes (use PostGIS instead)
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)
- 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
- 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)
- 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
- Storage Engine Specific: MyISAM/InnoDB specific behaviors
- Replication:
Binary logs, GTIDβ Now supported via CDC; master-slave admin commands still unsupported - MySQL-Specific Syntax: Some stored procedures, triggers, event syntax
- Stored Procedures: Need rewriting to PL/pgSQL
- Triggers: Need rewriting to PostgreSQL syntax
- Full-Text Search: Different syntax and functionality
For a detailed list of limitations, see DESIGN.md
- MySQL Compatibility List - Complete list of supported and unsupported MySQL features
- Quick Start Guide - Quick deployment and usage tutorial
- Design Document - Architecture design and technical decisions
- Operations Manual - Deployment, configuration, and troubleshooting
- Implementation Summary - Feature specifications and implementation details
- AST vs String Conversion Analysis - SQL rewriting architecture analysis
- MySQL Protocol Technical Notes - MySQL/PostgreSQL protocol implementation notes
- PostgreSQL Unsupported Features - MySQL feature compatibility checklist
- Test Organization Strategy - Test case classification and organization
- MySQL Test Coverage - Test case coverage details
- MySQL to PG Cases - SQL conversion examples
- Regex Optimization - SQL rewriting performance optimization
| 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
Issues and Pull Requests are welcome!
Apache License 2.0 - See LICENSE file for details
- go-mysql - MySQL protocol implementation
- pgx - PostgreSQL driver
- TiDB Parser - MySQL SQL parser