High severityconnection
MySQL Error:
2006
What does this error mean?
Error 2006 means the MySQL client had an active connection that the server closed unilaterally. The client sends a query or fetches a result set, but the TCP socket is already dead — the server hung up due to an idle timeout, a packet size violation, or an unplanned restart. In data pipelines this typically surfaces during long-running ETL jobs: an ADF copy activity finishes reading a batch, tries to fetch the next chunk 5 minutes later, and discovers the connection no longer exists. dbt models that compile slowly before execution are equally vulnerable. The visible symptom is a failed activity with exit code 2006 and the message 'MySQL server has gone away' in stderr or the connector log.
Common causes
- 1The connection sat idle longer than the server's wait_timeout (default 28800s on self-hosted, but as low as 120s on Azure Database for MySQL) and was reaped by the server.
- 2A single INSERT, LOAD DATA, or result set exceeded max_allowed_packet — the server immediately drops the connection without a graceful error response.
- 3The MySQL server process was restarted (planned maintenance, Azure failover, or OOM kill) while the client held an open connection.
- 4A network-level timeout (firewall, NAT gateway, or Azure NSG idle timeout of 4 minutes) silently closed the TCP socket between client and server.
- 5Connection pooling middleware (ProxySQL, PgBouncer-style wrappers) evicted the connection from the pool due to its own max-lifetime setting, but the client still held a reference.
- 6A long-running transaction triggered innodb_lock_wait_timeout, which in some configurations causes the server to kill the connection rather than just the statement.
How to fix it
- 1Step 1: Check the current timeout values: `SHOW GLOBAL VARIABLES LIKE '%timeout%';` — look at wait_timeout and interactive_timeout. On Azure Database for MySQL, check Server Parameters in the portal.
- 2Step 2: Increase wait_timeout to cover your longest pipeline run: `SET GLOBAL wait_timeout=28800; SET GLOBAL interactive_timeout=28800;` — on Azure, set via Server Parameters blade (requires server restart for static params).
- 3Step 3: Check and increase max_allowed_packet: `SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet';` then `SET GLOBAL max_allowed_packet=1073741824;` (1 GB) if you're transferring large BLOBs or wide rows.
- 4Step 4: In ADF, set the connection retry count on your MySQL linked service — open the linked service JSON and add `"connectRetryCount": 3, "connectRetryInterval": 10` to the typeProperties.
- 5Step 5: For dbt, add `connect_timeout: 28800` and `read_timeout: 28800` to your profiles.yml MySQL target. Also set `keepalives: 1` and `keepalives_idle: 60` if using TCP keepalives.
- 6Step 6: If behind a NAT gateway or Azure Firewall with a 4-minute idle timeout, enable TCP keepalives at the OS level: `sysctl -w net.ipv4.tcp_keepalive_time=60` on the client machine running the integration runtime.
- 7Step 7: Check MySQL error log for crash or restart events: `sudo tail -200 /var/log/mysql/error.log | grep -i 'shutdown\|restart\|killed'` — if you see OOM kills, address memory allocation before tuning timeouts.
Example log output
2026-05-11 03:14:22 ERROR mysql.connector.errors.OperationalError: 2006 (HY000): MySQL server has gone away
2026-05-11 03:14:22 ERROR Connection to mysql-prod-01.database.azure.com:3306 lost after 121s idle. Last query: SELECT * FROM orders WHERE updated_at > '2026-05-10'
2026-05-11 03:14:22 WARNING ADF Activity 'Copy_Orders_Incremental' failed with ErrorCode=UserErrorSourceConnectionError, retries exhausted (3/3).