Fix MySQL ERROR 2002 and ERROR 2003 connection failures
Diagnose MySQL ERROR 2002 and ERROR 2003 without guessing: separate a missing or mismatched Unix socket from a stopped service, wrong TCP port, bind-address policy, DNS, firewall, route, and certificate-verified TLS failure.
Restore the intended local socket and remote TLS connection to the intended MySQL server without opening port 3306 broadly, weakening certificate verification, moving the socket unsafely, or changing database credentials before transport is proven.
- MySQL Community Server 8.0, 8.4 LTS
- Ubuntu Server 22.04 LTS, 24.04 LTS
- RHEL-compatible Linux 8, 9
- Affected client boundary Run tests from the same host, container, namespace, account, and configuration path as the failing application; a successful test from a bastion proves a different route.
- Server observation access Keep read-only shell access to the intended database host and permission to inspect the MySQL service, listeners, logs, and effective startup options.
- Independent recovery path Retain console access and a protected copy of the current MySQL and firewall configuration before any restart or listener change.
- Network ownership Know the approved client source range, database address, port, firewall owner, and whether a proxy, load balancer, VPN, container network, or service mesh is part of the path.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- A repeatable MySQL incident record that starts with the literal `ERROR 2002 (HY000): Can't connect to local MySQL server through socket` or `ERROR 2003 (HY000): Can't connect to MySQL server on 'host:3306'` symptom and preserves the first useful failure instead of hiding it with an early restart or broad permission change.
- A layer-by-layer decision path from client context through configuration and runtime evidence to one narrowly scoped remediation, followed by positive and negative verification.
- A reusable evidence bundle containing commands, concrete example output, timestamps, identities, effective configuration, and stop conditions that another operator can review without access to the original terminal.
- You can identify which boundary failed, explain why competing hypotheses were rejected, and state what changed before declaring the incident resolved.
- The repaired path succeeds under the intended identity while an unauthorized or incorrect path still fails, proving that the fix did not simply remove a security control.
- The final evidence distinguishes a transient recovery from a durable repair by checking logs, counters, configuration provenance, and the original user-visible operation.
Architecture
How the parts fit together
MySQL troubleshooting is treated as an evidence pipeline rather than a list of guesses. The operator captures the symptom, resolves client and target context, inspects the first authoritative server-side failure, tests the smallest cause boundary, applies one reviewed change, and repeats the same observation path. This keeps a secondary error from replacing the primary cause and makes rollback possible.
- Copy the literal error and the command that produced it before retrying, restarting, pruning, resetting, or editing anything.
- Resolve the selected identity, configuration, target, and current runtime state so later commands inspect the same path the user exercised.
- Read the nearest authoritative log or effective configuration and align timestamps across the client and server evidence.
- Test one hypothesis with a read-only command; if evidence disagrees, return to the previous layer instead of stacking speculative changes.
- Back up the affected configuration or reference, apply the narrow repair, validate syntax, and reload only the component that owns the decision.
- Repeat the original action plus a negative control, record the outcome, and keep rollback material until the observation window is complete.
Assumptions
- The target is a Linux MySQL server managed by systemd; distribution unit names and option-file locations are verified rather than assumed.
- Remote clients should use TCP with a narrow network policy and certificate verification; local administration may use a protected Unix socket.
- ERROR 2002 and ERROR 2003 are transport-establishment failures. Account passwords and grants are out of scope until a MySQL handshake reaches authentication.
- A production restart, bind-address change, firewall change, or socket relocation requires a maintenance decision and a tested rollback path.
- Clocks are close enough that client and server timestamps can be correlated. If they are not, record the offset before comparing logs.
- The operator has a recovery path that does not depend on the component being changed, such as console access, a second session, or a preserved remote reference.
- Commands are first run in the affected environment with placeholders reviewed. OneLiners never executes them and does not know local policy, tenancy, or maintenance constraints.
Key concepts
- Unix socket
- A filesystem endpoint used by local clients. On Unix, omitting `--host` or using `localhost` normally selects a socket instead of TCP, so client and server must agree on the exact path and directory permissions.
- TCP listener
- The address-and-port endpoint opened by mysqld. A running process is not proof that it listens on the interface and port used by the client.
- Connection refused
- A fast TCP rejection usually means the destination host is reachable but no process accepts that address and port, or a firewall actively rejects it. It differs from a timeout, which often indicates a dropped packet or broken route.
- bind_address
- A non-dynamic MySQL startup setting that controls which local network addresses accept ordinary client TCP connections. A loopback-only bind intentionally blocks remote access.
- skip_networking
- A MySQL startup setting that disables ordinary TCP/IP connections entirely, leaving local non-TCP transports such as the Unix socket.
- VERIFY_IDENTITY
- A MySQL client TLS mode that validates the server certificate chain and checks that its identity matches the host name used by the client.
Fill these once. Every matching command and configuration block updates immediately; values stay in this page only.
Security and production boundaries
- A database listener is a privileged network boundary. Bind only to required private interfaces and restrict every firewall or security-group rule to approved sources.
- Do not disable `VERIFY_IDENTITY`, use `--ssl-mode=DISABLED`, or replace a DNS service name with an unverified IP to make a remote test pass.
- Transport diagnosis does not require a password in command arguments. Use a prompt, login path, workload secret manager, or a purpose-specific least-privilege probe identity.
- Treat unexpected public reachability, unknown listener ownership, repeated probes from unapproved networks, or a changed certificate as a security incident rather than an availability-only problem.
- Do not paste private keys, tokens, complete environment dumps, authorization headers, or unredacted customer data into tickets or external analysis tools.
- A successful operation after disabling authentication, trust, host verification, sandboxing, or least privilege is a security regression, not a valid repair.
- Prefer effective configuration and narrow identity tests over recursive ownership changes, mode 777, global trust bypasses, or force options copied from unrelated incidents.
Stop before continuing if
- Stop before restarting if active workload, replication, backup, failover, and recovery access are not understood.
- Stop if the proposed solution opens MySQL publicly, disables TLS verification, changes credentials before transport works, or creates an unmanaged socket path.
- Stop when DNS, route, or listener evidence identifies another host or server UUID than the approved database instance.
- Stop and escalate on corruption, crash loops, full disk, unexplained certificate changes, or traffic from unapproved sources.
- Stop if the target, account, environment, repository, or service instance cannot be identified unambiguously.
- Stop before a destructive cleanup, force update, broad permission change, or production reload when backup and recovery evidence is missing.
- Stop if the proposed action would conceal the first error or remove logs, failed objects, repository references, or configuration needed for diagnosis.
instruction
Freeze the symptom and define the incident boundary
Before changing MySQL, preserve the literal `ERROR 2002 (HY000): Can't connect to local MySQL server through socket` or `ERROR 2003 (HY000): Can't connect to MySQL server on 'host:3306'` message, the exact action that produced it, the affected identity, target, UTC time, and expected result. Decide which production boundary is in scope and name the independent recovery path you will keep available.
Why this step matters
A retry, restart, cleanup, permission change, or configuration edit can replace the primary failure with a secondary one. A fixed starting record lets every later check answer a specific hypothesis.
What to understand
Record whether the problem affects one user or workload, one target, one host, or every comparable path; this determines whether to begin at the client, transport, or service boundary.
Write down the expected successful behavior in observable terms such as an exit status, HTTP response, remote object ID, authenticated principal, or stable service state.
Keep console access, a second session, an earlier configuration, or a recoverable reference independent of the component being diagnosed.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Incident scope Tool: MySQL Observed: `ERROR 2002 (HY000): Can't connect to local MySQL server through socket` or `ERROR 2003 (HY000): Can't connect to MySQL server on 'host:3306'` Affected target: production-app-01 Observed at: 2026-08-17T14:02:11Z Expected: the reviewed operation completes without weakening an access or safety control Recovery path: console session and last known-good configuration retained
Security notes
- Redact secrets and customer data, but retain error text, timestamps, object IDs, modes, owners, and target names needed to reproduce the decision.
Alternatives
- When direct production inspection is restricted, reproduce the same version and configuration boundary in an isolated environment and mark which evidence is illustrative.
Stop conditions
- Stop before any mutation if the target, identity, affected environment, expected result, or recovery path is still ambiguous.
command
Reproduce ERROR 2002 and ERROR 2003 with explicit transports
Capture the literal client failure from the affected runtime, then force socket and TCP tests separately. This prevents `localhost`, option files, or an inherited environment from silently switching transport while you diagnose a different path.
Why this step matters
MySQL selects a Unix socket for local connections under common defaults and TCP for an explicit remote host. Testing both with bounded timeouts reveals whether one endpoint, both endpoints, or only inherited client configuration is wrong.
What to understand
Record the numeric operating-system error in parentheses: `2` commonly accompanies a missing path, `13` a permission denial, `111` a refusal, and a long timeout points to a different network boundary. Interpret the number on the actual operating system rather than treating it as a MySQL server code.
Review `--print-defaults` for host, port, socket, protocol, and SSL selection. Do not publish the output until any credential or private path material has been removed.
A socket success with TCP failure proves mysqld is running but does not prove it should accept remote connections. A TCP success with socket failure points to client/server socket-path selection rather than account policy.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
--protocol=SOCKET / --socket- Forces the local filesystem transport and exact socket path instead of allowing `localhost` defaults to choose implicitly.
--protocol=TCP / --host / --port- Forces the intended network endpoint, separating it from a local socket test.
--connect-timeout=3- Bounds each diagnostic attempt so a dropped network path does not hold the incident terminal indefinitely.
--ssl-mode=VERIFY_IDENTITY- Requires encryption, trusted CA validation, and host-name identity verification after TCP establishment.
Values stay on this page and are never sent or saved.
mysql --print-defaults; mysqladmin --protocol=SOCKET --socket={{socketPath}} --connect-timeout=3 ping; mysqladmin --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=3 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} pingmysql would have been started with the following arguments: --socket=/var/run/mysqld/mysqld.sock --host=db01.example.net --port=3306 mysqladmin: connect to server at 'localhost' failed error: 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)' ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) mysqladmin: connect to server at 'db01.example.net' failed error: 'Can't connect to MySQL server on 'db01.example.net:3306' (111)' ERROR 2003 (HY000): Can't connect to MySQL server on 'db01.example.net:3306' (111)
Checkpoint: Checkpoint: Reproduce ERROR 2002 and ERROR 2003 with explicit transports
mysql --print-defaults; mysqladmin --protocol=SOCKET --socket={{socketPath}} --connect-timeout=3 ping; mysqladmin --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=3 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} pingContinue whenThe evidence names the selected socket, DNS host, port, transport, exact ERROR 2002 or ERROR 2003 text, elapsed behavior, and affected client context.
Stop whenThe command resolves to another host, exposes a credential, selects an unexplained proxy or defaults file, or the certificate name cannot match the supplied IP address.
If this step fails
`mysql --print-defaults` reveals a stale socket or host from an option file.
Likely causeThe application and interactive shell load different global, user, login-path, container, or service configuration and therefore never target the same endpoint.
my_print_defaults client mysql mysqladminmysql_config_editor print --all
ResolutionCorrect the one owned configuration source and restart only the affected application process. Do not create a second socket or listener to satisfy an obsolete path.
Security notes
- Do not use `--password=...`, print environment secrets, or attach an unredacted option dump to the incident. A transport failure does not require exposing a database credential.
Alternatives
- Use the application's built-in connection diagnostics when it reports the resolved host, port, socket, protocol, TLS mode, and timeout without logging the password.
Stop conditions
- The command resolves to another host, exposes a credential, selects an unexplained proxy or defaults file, or the certificate name cannot match the supplied IP address.
command
Inspect the MySQL service and first startup failure
On the intended database host, identify the real unit, active state, main process result, and recent journal before restarting anything. A failed unit can explain both a missing socket and a refused TCP port, while an active unit moves the investigation to listeners and namespaces.
Why this step matters
The earliest authoritative startup error is more useful than an application retry. An invalid address, occupied port, inaccessible data directory, full disk, bad option, or damaged server can all prevent both endpoints from being created.
What to understand
Confirm the host identity and unit selected by packaging. Ubuntu commonly uses `mysql.service`; RHEL-family packages may expose `mysqld.service`; aliases can point to the same loaded unit.
Preserve the journal lines before a restart rotates or interleaves them. If the server crash-loops, stop automation from repeatedly replacing the first failure before changing configuration.
A service shown as active can still be a different instance, namespace, container, or port. Continue to socket and listener evidence rather than assuming availability.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
systemctl show- Returns stable unit state, result, and process fields without the formatting and truncation of the human status view.
journalctl --since- Bounds authoritative service evidence to the incident window and keeps timestamps for correlation.
systemctl is-active mysql.service 2>/dev/null || systemctl is-active mysqld.service; systemctl show mysql.service mysqld.service -p Id -p LoadState -p ActiveState -p SubState -p Result -p MainPID --no-pager 2>/dev/null; sudo journalctl -u mysql.service -u mysqld.service --since '30 minutes ago' --no-pager | tail -n 120failed Id=mysql.service LoadState=loaded ActiveState=failed SubState=failed Result=exit-code MainPID=0 Aug 18 10:12:03 db01 mysqld[2284]: [ERROR] [MY-000077] [Server] /usr/sbin/mysqld: Error while setting value '10.20.40.15' to 'bind_address'. Aug 18 10:12:03 db01 systemd[1]: mysql.service: Failed with result 'exit-code'.
Checkpoint: Checkpoint: Inspect the MySQL service and first startup failure
systemctl is-active mysql.service 2>/dev/null || systemctl is-active mysqld.service; systemctl show mysql.service mysqld.service -p Id -p LoadState -p ActiveState -p SubState -p Result -p MainPID --no-pager 2>/dev/null; sudo journalctl -u mysql.service -u mysqld.service --since '30 minutes ago' --no-pager | tail -n 120Continue whenThe intended MySQL unit is either healthy with a stable MainPID or has one preserved startup failure that explains why no endpoint exists.
Stop whenThe journal reports data corruption, disk exhaustion, permission changes, unknown configuration ownership, or repeated crashes that require a dedicated recovery procedure.
If this step fails
No mysql or mysqld unit exists on the host.
Likely causeThe database runs in a container, under another service manager, on another host, or the package was removed while clients still target this machine.
ps -eo pid,user,comm,args | grep '[m]ysqld'sudo ss -lxnp | grep -i mysql; sudo ss -lntp | grep ':3306'
ResolutionLocate the documented owner and runtime before taking action. Do not install a second server or initialize a new data directory over an unknown deployment.
Security notes
- Error logs can contain schema names, paths, addresses, and client identifiers. Redact them externally but preserve exact option names and timestamps for the operator record.
Alternatives
- Use the orchestrator's read-only workload status and log commands when MySQL is intentionally containerized or managed by a platform service.
Stop conditions
- The journal reports data corruption, disk exhaustion, permission changes, unknown configuration ownership, or repeated crashes that require a dedicated recovery procedure.
command
Map the real Unix socket and TCP listeners
Inspect kernel-owned Unix and TCP listening endpoints, their processes, path metadata, network namespaces, and MySQL runtime directory. This proves what exists now rather than what a configuration file claims should exist.
Why this step matters
Kernel listener tables connect each endpoint to a live process. Socket path traversal and the local TCP address reveal missing directories, permission boundaries, loopback-only binds, stale files, and namespace mistakes without changing the service.
What to understand
A socket entry tied to mysqld is authoritative. A plain filesystem object without an `ss` listener may be stale and must not be deleted until the owning service and active clients are understood.
A listener on `127.0.0.1:3306` accepts local TCP only. Opening the host firewall cannot make that listener accept packets addressed to another interface.
Containers have their own namespaces. Run listener inspection in the namespace that owns mysqld and separately verify the published host or service endpoint.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
ss -lxnp- Lists listening Unix sockets with process ownership and exact filesystem paths.
ss -lntp 'sport = :port'- Lists numeric TCP listeners for the selected source port and owning process without relying on DNS.
namei -l- Shows owner and mode for every directory component leading to the socket.
Values stay on this page and are never sent or saved.
sudo ss -lxnp | grep -E 'mysql|mysqld|{{socketPath}}' || true; sudo ss -lntp 'sport = :{{dbPort}}'; sudo stat -Lc 'type=%F owner=%U group=%G mode=%a path=%n' {{socketPath}} 2>&1; sudo namei -l {{socketPath}}u_str LISTEN 0 151 /var/run/mysqld/mysqld.sock 42018 * 0 users:(("mysqld",pid=2410,fd=22))
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 151 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=2410,fd=24))
type=socket owner=mysql group=mysql mode=777 path=/var/run/mysqld/mysqld.sock
f: /var/run/mysqld/mysqld.sock
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root run
drwxr-xr-x mysql mysql mysqld
srwxrwxrwx mysql mysql mysqld.sockCheckpoint: Checkpoint: Map the real Unix socket and TCP listeners
sudo ss -lxnp | grep -E 'mysql|mysqld|{{socketPath}}' || true; sudo ss -lntp 'sport = :{{dbPort}}'; sudo stat -Lc 'type=%F owner=%U group=%G mode=%a path=%n' {{socketPath}} 2>&1; sudo namei -l {{socketPath}}Continue whenThe live mysqld process owns the expected socket and/or approved TCP address and port; every difference from the client target is named.
Stop whenAnother process owns the endpoint, the socket is outside the approved runtime directory, the listener is unexpectedly public, or the database runs in an unidentified namespace.
If this step fails
The socket file exists but no process listens on it.
Likely causemysqld terminated without cleanup, the path is a bind-mounted stale object, or another namespace owns the actual listener.
sudo lsof -U -- {{socketPath}}sudo findmnt -T {{socketPath}}
ResolutionProve no process or namespace uses the path, repair the service's controlled runtime-directory lifecycle, and let mysqld recreate the socket. Do not remove it based on file age alone.
Security notes
- Do not use `chmod 777` on the socket directory as a repair. Directory traversal and socket access should follow the distribution service policy and local account boundary.
Alternatives
- Use `lsof -U` and `lsof -iTCP:{{dbPort}} -sTCP:LISTEN` when the installed `ss` lacks process or Unix-socket details.
Stop conditions
- Another process owns the endpoint, the socket is outside the approved runtime directory, the listener is unexpectedly public, or the database runs in an unidentified namespace.
command
Resolve effective socket, port, bind, and networking configuration
Compare startup defaults, systemd arguments, included option files, and—when the socket works—the running server variables. The aim is to identify the one authoritative setting rather than editing every file containing `port` or `socket`.
Why this step matters
MySQL reads layered option files and service arguments at startup. The running value is authoritative for the current process; defaults and unit definitions explain where a reviewed persistent repair belongs.
What to understand
`bind_address` and `skip_networking` are startup choices, not quick dynamic toggles. A change requires validation and a controlled restart, so prove the requirement first.
Do not replace a loopback bind with `0.0.0.0` automatically. Bind to the approved private address or documented interface set and keep a source-restricted firewall in front of it.
Keep the server and every local client aligned on one absolute socket path. On systemd systems, prefer a managed runtime directory that is recreated with correct ownership at boot.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
my_print_defaults- Prints the merged options selected for named MySQL program groups, exposing persistent path, port, and bind choices.
systemctl cat- Shows the vendor unit and local drop-ins that can add startup arguments or namespace restrictions.
mysqladmin variables- Reads values from the running server over the independent socket path when that transport is healthy.
Values stay on this page and are never sent or saved.
my_print_defaults mysqld server mysqladmin; systemctl cat mysql.service mysqld.service 2>/dev/null; sudo mysqladmin --protocol=SOCKET --socket={{socketPath}} variables 2>/dev/null | grep -E '\| (socket|port|bind_address|skip_networking) ' || true--user=mysql --socket=/var/run/mysqld/mysqld.sock --port=3306 --bind-address=127.0.0.1 # /lib/systemd/system/mysql.service ExecStart=/usr/sbin/mysqld | bind_address | 127.0.0.1 | | port | 3306 | | skip_networking| OFF | | socket | /var/run/mysqld/mysqld.sock |
Checkpoint: Checkpoint: Resolve effective socket, port, bind, and networking configuration
my_print_defaults mysqld server mysqladmin; systemctl cat mysql.service mysqld.service 2>/dev/null; sudo mysqladmin --protocol=SOCKET --socket={{socketPath}} variables 2>/dev/null | grep -E '\| (socket|port|bind_address|skip_networking) ' || trueContinue whenOne documented configuration source explains the live socket, TCP port, bind address, and networking state, including any deliberate local-only policy.
Stop whenMultiple unmanaged files conflict, the value is automation-owned, the intended interface is unknown, or remote access is not approved for this server.
If this step fails
`my_print_defaults` and running variables disagree.
Likely causeThe service uses a different defaults file, command-line override, container configuration, or an old process that has not loaded the current files.
tr '\0' ' ' </proc/$(pgrep -xo mysqld)/cmdlinesudo systemctl show mysql.service mysqld.service -p ExecStart -p Environment --no-pager
ResolutionIdentify the process's real startup source and reconcile it through the owning deployment workflow. Do not restart until the proposed effective configuration is reviewed.
Security notes
- Do not copy option files or process environments without redaction; they can contain credentials, key paths, replication endpoints, and internal topology.
Alternatives
- Use the managed database or container platform's effective-configuration view when host-level option files are not the source of truth.
Stop conditions
- Multiple unmanaged files conflict, the value is automation-owned, the intended interface is unknown, or remote access is not approved for this server.
command
Trace DNS, route, port, and firewall from the real client
From the affected client boundary, resolve every address, record the selected route and source, and probe only the intended port. On the server, confirm the destination address belongs to the host and inspect the active firewall rules that govern the approved source.
Why this step matters
DNS, routing, listener binding, and firewall policy are independent layers. Capturing the selected source and destination on both ends prevents a broad firewall opening from hiding a wrong address or absent listener.
What to understand
Test every returned address when clients can choose IPv4 or IPv6; one stale AAAA record can create intermittent failures even when the IPv4 endpoint is healthy.
A refusal usually returns quickly; a timeout often means silent filtering, an asymmetric route, failed VPN, security group, or unreachable address. Measure behavior from the application namespace, not only from an operator laptop.
Host nftables may be only one policy layer. Cloud security groups, network ACLs, Kubernetes NetworkPolicy, VPN rules, proxies, and physical firewalls require evidence from their owners.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
getent ahosts- Uses the host's configured name-service path and exposes all returned IPv4 and IPv6 candidates.
ip route get- Shows the kernel-selected egress interface, gateway, and source address for the destination.
nc -vz -w 3- Attempts a bounded TCP handshake without sending database credentials or application queries.
nft list ruleset- Reads the active nftables rules rather than assuming a front-end command reflects every chain and table.
Values stay on this page and are never sent or saved.
getent ahosts {{dbHost}}; ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}'); nc -vz -w 3 {{dbHost}} {{dbPort}}; sudo ip -brief address; sudo nft list ruleset | grep -C 4 -E '{{dbPort}}|{{clientAddress}}'10.20.40.15 STREAM db01.example.net 10.20.40.15 DGRAM db01.example.net 10.20.40.15 via 10.20.30.1 dev eth0 src 10.20.30.44 uid 1001 nc: connect to db01.example.net (10.20.40.15) port 3306 (tcp) failed: Connection refused eth0 UP 10.20.40.15/24 tcp dport 3306 ip saddr 10.20.30.0/24 ct state new accept
Checkpoint: Checkpoint: Trace DNS, route, port, and firewall from the real client
getent ahosts {{dbHost}}; ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}'); nc -vz -w 3 {{dbHost}} {{dbPort}}; sudo ip -brief address; sudo nft list ruleset | grep -C 4 -E '{{dbPort}}|{{clientAddress}}'Continue whenDNS resolves only approved addresses, the client uses the expected source and route, the server owns the destination, and every firewall layer permits only the intended client range to the live listener.
Stop whenDNS points outside the approved estate, the route crosses an unknown network, the client source differs from policy, or the proposed repair exposes MySQL to the public internet.
If this step fails
The port works from a bastion but times out from the application container.
Likely causeThe two clients use different DNS, address family, route, NAT source, namespace firewall, VPN, or network policy.
getent ahosts {{dbHost}}; ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}')nc -vz -w 3 {{dbHost}} {{dbPort}}
ResolutionCapture and approve the application's actual source-to-destination path, then change the narrow owning policy. Do not copy the bastion's broader access rule.
Security notes
- Never open 3306 to `0.0.0.0/0` for testing. Use a temporary time-bounded rule for the exact reviewed source only when the policy owner approves and records automatic removal.
Alternatives
- Use the platform's flow logs or a server-side packet capture limited to the client and port when firewall ownership prevents direct ruleset inspection.
Stop conditions
- DNS points outside the approved estate, the route crosses an unknown network, the client source differs from policy, or the proposed repair exposes MySQL to the public internet.
command
Verify the MySQL handshake and certificate identity
Once TCP accepts connections, use the real MySQL client to require the CA and host-name identity checks. A plain port probe cannot prove that the listener speaks MySQL, presents the intended certificate, or accepts the required TLS policy.
Why this step matters
The MySQL client negotiates the database protocol before TLS and can verify both the trusted CA and the host identity. This distinguishes a healthy transport from a proxy, stale certificate, wrong server, or insecure fallback.
What to understand
Use a least-privilege probe identity or the application's protected credential. The probe needs only enough access to authenticate and run the selected metadata query.
Connect with the DNS name present in the certificate. Replacing it with an IP address to bypass DNS often makes correct host-name verification fail and can hide a routing error.
A non-empty `Ssl_cipher` confirms encryption for this session. The successful `VERIFY_IDENTITY` connection also proves CA and name verification for the selected host.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
--ssl-mode=VERIFY_IDENTITY- Requires TLS, verifies the certificate chain, and matches the certificate identity to the supplied host name.
--ssl-ca- Selects the trusted CA bundle used to validate the server certificate.
SHOW SESSION STATUS LIKE 'Ssl_cipher'- Reports the cipher negotiated by this exact session; an empty value means encryption is not in use.
Values stay on this page and are never sent or saved.
mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --execute="SELECT @@hostname AS server, @@port AS port; SHOW SESSION STATUS LIKE 'Ssl_cipher';"Enter password: server port db01 3306 Variable_name Value Ssl_cipher TLS_AES_256_GCM_SHA384
Checkpoint: Checkpoint: Verify the MySQL handshake and certificate identity
mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --execute="SELECT @@hostname AS server, @@port AS port; SHOW SESSION STATUS LIKE 'Ssl_cipher';"Continue whenThe intended server and port answer over a certificate-verified connection and report a non-empty TLS cipher before application queries are tested.
Stop whenThe certificate is untrusted, expired, names another host, the listener is not MySQL, or the only proposed workaround is `PREFERRED`, `DISABLED`, or disabled host verification.
If this step fails
TCP connects, but VERIFY_IDENTITY reports a certificate name mismatch.
Likely causeDNS points to the wrong server, the certificate lacks the selected host name, a proxy presents another certificate, or the client used an IP address not covered by the certificate.
getent ahosts {{dbHost}}mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password
ResolutionCorrect DNS, routing, proxy identity, or issue a certificate for the documented service name. Do not suppress host verification.
Security notes
- Use an interactive password prompt or protected login path. Do not put the credential in process arguments, shell history, tickets, or example output.
Alternatives
- Use the approved application driver with equivalent CA and host-name verification, then record its resolved endpoint, certificate identity, and negotiated TLS state.
Stop conditions
- The certificate is untrusted, expired, names another host, the listener is not MySQL, or the only proposed workaround is `PREFERRED`, `DISABLED`, or disabled host verification.
decision
Apply one reviewed endpoint or policy repair
Change only the layer proven wrong: align the client socket path, restore the managed runtime directory, correct one owned DNS record, bind mysqld to an approved private address, enable the documented TCP listener, or permit the exact client range. Validate MySQL configuration before a controlled restart and preserve the prior configuration and firewall rules.
Why this step matters
A validated, single-layer change is auditable and reversible. Restarting only after syntax validation avoids replacing a reachable but misbound server with a failed service, while immediate listener checks expose whether the intended endpoints returned.
What to understand
For a client-only socket mismatch, change the client's owned option file and avoid a server restart. For a missing runtime directory, repair the service manager's RuntimeDirectory or packaging configuration rather than creating an unmanaged boot script.
For remote access, bind to the reviewed private address or interface set and keep firewall permission limited to approved client sources. Listener exposure and authorization are two separate controls and both must remain narrow.
A restart terminates active sessions and can affect replication, backups, failover, and connection pools. Confirm workload impact and maintenance ownership before executing this step.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- May reload a corrected client setting or restart MySQL after a reviewed socket, bind, port, DNS, or firewall change. It can interrupt sessions and alter network reachability, so it requires a maintenance and rollback decision.
Syntax explained
mysqld --validate-config- Checks MySQL startup options for validation errors before the running service is disturbed.
systemctl restart- Stops and starts the service so non-dynamic socket, port, bind, and networking settings take effect; it is intentionally classified as caution.
systemctl is-active / ss- Immediately proves service state and the exact endpoints created by the new process.
Values stay on this page and are never sent or saved.
sudo mysqld --validate-config && sudo systemctl restart mysql.service && sudo systemctl is-active mysql.service && sudo ss -lxnp | grep -F '{{socketPath}}' && sudo ss -lntp 'sport = :{{dbPort}}'active
u_str LISTEN 0 151 /var/run/mysqld/mysqld.sock 45822 * 0 users:(("mysqld",pid=3188,fd=22))
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 151 10.20.40.15:3306 0.0.0.0:* users:(("mysqld",pid=3188,fd=24))Checkpoint: Checkpoint: Apply one reviewed endpoint or policy repair
sudo mysqld --validate-config && sudo systemctl restart mysql.service && sudo systemctl is-active mysql.service && sudo ss -lxnp | grep -F '{{socketPath}}' && sudo ss -lntp 'sport = :{{dbPort}}'Continue whenThe service validates and becomes active, only the intended socket and private listener appear, and the previous configuration and firewall state remain available for rollback.
Stop whenValidation fails, active sessions cannot be drained, replication or backup state is unknown, console access is missing, or the listener would become broader than the approved network boundary.
If this step fails
The service fails after the restart even though validation passed.
Likely causeThe new address is absent at runtime, the port is occupied, runtime paths or key files are inaccessible, or validation did not exercise an external dependency.
sudo journalctl -u mysql.service --since '-5 minutes' --no-pagersudo ss -lxnp; sudo ss -lntp 'sport = :{{dbPort}}'
ResolutionRestore the protected configuration and firewall snapshot, start the last known-good service, verify its endpoints, and investigate the captured first failure before another attempt.
Security notes
- Do not combine this repair with account grants, password resets, disabled TLS, wildcard binds, or public firewall access. Those changes erase evidence and enlarge the incident scope.
Alternatives
- When a restart is unsafe, restore service through the approved failover or managed-database operation and schedule the persistent endpoint correction in a controlled window.
Stop conditions
- Validation fails, active sessions cannot be drained, replication or backup state is unknown, console access is missing, or the listener would become broader than the approved network boundary.
command
Verify local socket, remote TLS, and a negative network control
Repeat the original tests from the real local and remote boundaries. Prove server UUID, endpoint, transport, and TLS cipher, then confirm an unapproved source or wrong port remains blocked. Finally reconnect the application and observe its pool rather than relying on one operator session.
Why this step matters
Matching server UUIDs prove local and remote tests reach the same instance. The explicit socket, host, port, TLS cipher, and negative control show that availability returned without opening an unintended service boundary.
What to understand
Run the remote test from the application namespace and source address, not only from the database host. Recycle only the affected pool after the endpoint and secret revision are confirmed.
Use a deliberately closed test port or an approved unprivileged source as the negative control. Never generate destructive SQL merely to prove denial.
Observe connection errors, abort counters, service logs, and application health for a bounded period that includes normal pool refresh and scheduled jobs.
Record the command, UTC timestamp, exit status, and the exact output before moving to the next layer. A later successful command must not erase evidence of the original failure.
Interpret this result together with the previous checkpoint. One matching line is evidence for a hypothesis, not permission to apply every commonly suggested fix.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Syntax explained
@@server_uuid- Identifies the exact MySQL instance reached through each transport, preventing a healthy test against a replica or different server from closing the incident.
@@socket / @@port- Reports the server's active local socket and ordinary TCP port for comparison with client configuration.
nc to a closed port- Provides a harmless negative reachability control showing the observed success is specific to the approved listener.
Values stay on this page and are never sent or saved.
sudo mysql --protocol=SOCKET --socket={{socketPath}} --batch --execute="SELECT @@server_uuid AS server_uuid, @@socket AS socket, @@port AS port;"; mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --batch --execute="SELECT @@server_uuid AS server_uuid, @@hostname AS server; SHOW SESSION STATUS LIKE 'Ssl_cipher';"; nc -vz -w 3 {{dbHost}} 3307server_uuid socket port 88f62f56-5d44-11ee-9f3a-0242ac120002 /var/run/mysqld/mysqld.sock 3306 Enter password: server_uuid server 88f62f56-5d44-11ee-9f3a-0242ac120002 db01 Variable_name Value Ssl_cipher TLS_AES_256_GCM_SHA384 nc: connect to db01.example.net (10.20.40.15) port 3307 (tcp) failed: Connection refused
Checkpoint: Checkpoint: Verify local socket, remote TLS, and a negative network control
sudo mysql --protocol=SOCKET --socket={{socketPath}} --batch --execute="SELECT @@server_uuid AS server_uuid, @@socket AS socket, @@port AS port;"; mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --batch --execute="SELECT @@server_uuid AS server_uuid, @@hostname AS server; SHOW SESSION STATUS LIKE 'Ssl_cipher';"; nc -vz -w 3 {{dbHost}} 3307Continue whenLocal and remote paths reach the same intended server UUID, the remote session verifies TLS identity, the application reconnects, and the negative control remains unavailable.
Stop whenThe UUIDs differ, the application resolves another endpoint, TLS lacks a cipher, errors recur during pool refresh, or unintended sources can reach the listener.
If this step fails
Operator tests succeed, but the application still returns ERROR 2003.
Likely causeThe application uses another DNS view, container namespace, address family, proxy, port, stale pool, configuration revision, or network policy.
getent ahosts {{dbHost}}; ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}')mysql --print-defaults
ResolutionCapture the endpoint and route inside the application process boundary, deploy the owned configuration, and recycle only its connections after proving the new revision.
Security notes
- Retain only redacted server UUID, address, route, listener, and TLS evidence. Do not retain probe credentials or private key material in the incident record.
Alternatives
- Use an application health endpoint that reports server UUID, selected endpoint, driver TLS state, and configuration revision without disclosing a password.
Stop conditions
- The UUIDs differ, the application resolves another endpoint, TLS lacks a cipher, errors recur during pool refresh, or unintended sources can reach the listener.
verification
Observe for recurrence and close with evidence
After the original MySQL operation succeeds, repeat the same read-only observation path used at the start. Watch the relevant logs, counters, identities, and target state for a bounded period, then record the proven cause, exact change, verification result, rollback point, and remaining uncertainty.
Why this step matters
A single successful retry may be a transient recovery. Repeating the original checks and retaining the rollback point distinguishes a durable repair from a restart-only improvement.
What to understand
Use the same client identity, target, path, and configuration selection as the original failure so the positive result is comparable.
Include one negative or unauthorized control where safe; this proves the repair did not work by removing authentication, trust, isolation, or branch protection.
Keep the evidence concise enough for another operator to reproduce, but include software versions and exact object or configuration references.
System changes
- No persistent change. This step reads current configuration, identity, runtime state, or logs and records evidence for the incident timeline.
Observation window: 15 minutes Original operation: PASS Original signature recurrences: 0 Negative control: PASS Rollback point retained: yes Cause and repair recorded: yes Remaining uncertainty: none observed within the stated boundary
Checkpoint: Checkpoint: the repair remains valid
sudo mysql --protocol=SOCKET --socket={{socketPath}} --batch --execute="SELECT @@server_uuid AS server_uuid, @@socket AS socket, @@port AS port;"; mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --batch --execute="SELECT @@server_uuid AS server_uuid, @@hostname AS server; SHOW SESSION STATUS LIKE 'Ssl_cipher';"; nc -vz -w 3 {{dbHost}} 3307Continue whenThe intended operation stays healthy, the original signature does not recur, and the negative control still enforces the expected boundary.
Stop whenThe result depends on an unexplained retry, disabled control, different target, or unrecorded manual state.
If this step fails
The error returns during the observation window.
Likely causeThe change treated a symptom, another instance still has the old state, or an automated process reverted or recreated the failing condition.
mysql --print-defaults; mysqladmin --protocol=SOCKET --socket={{socketPath}} --connect-timeout=3 ping; mysqladmin --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=3 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} pingsudo mysql --protocol=SOCKET --socket={{socketPath}} --batch --execute="SELECT @@server_uuid AS server_uuid, @@socket AS socket, @@port AS port;"; mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --batch --execute="SELECT @@server_uuid AS server_uuid, @@hostname AS server; SHOW SESSION STATUS LIKE 'Ssl_cipher';"; nc -vz -w 3 {{dbHost}} 3307
ResolutionPreserve the recurrence, compare it with the first evidence set, restore the known-good state if necessary, and reopen the unresolved layer instead of stacking another repair.
Security notes
- Store only redacted operational evidence and remove temporary debug output according to local retention policy after review.
Alternatives
- Use the service's approved monitoring or audit trail when an interactive observation window is not practical.
Stop conditions
- Do not close the incident while the result is intermittent, the rollback point is missing, or a safety control remains weakened.
Finish line
Verification checklist
sudo mysql --protocol=SOCKET --socket={{socketPath}} --batch --execute="SELECT @@server_uuid AS server_uuid, @@socket AS socket, @@port AS port;"; mysql --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=5 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password --batch --execute="SELECT @@server_uuid AS server_uuid, @@hostname AS server; SHOW SESSION STATUS LIKE 'Ssl_cipher';"; nc -vz -w 3 {{dbHost}} 3307The operation completes with exit status 0 and without the original error. The output identifies the intended host, service, repository, or endpoint.mysql --print-defaults; mysqladmin --protocol=SOCKET --socket={{socketPath}} --connect-timeout=3 ping; mysqladmin --protocol=TCP --host={{dbHost}} --port={{dbPort}} --connect-timeout=3 --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} pingA fresh diagnostic capture shows the healthy path and no recurrence of the original signature. Logs and counters remain stable during the observation window.Recovery guidance
Common problems and safe checks
ERROR 2002 includes `(2)` and the named socket path does not exist.
Likely causemysqld is stopped, the server creates another socket path, the runtime directory was removed, or the client loads a stale option file.
systemctl is-active mysql.service mysqld.servicesudo ss -lxnp | grep -i mysql; my_print_defaults mysqld mysql
ResolutionRestore the owned service or align the client to the one live socket. Do not create a symlink until path ownership, boot lifecycle, and every client are reviewed.
ERROR 2002 includes `(13)` even though the socket exists.
Likely causeThe client identity cannot traverse a parent directory, access is blocked by SELinux/AppArmor, or the socket is mounted into a container with incompatible ownership.
namei -l {{socketPath}}sudo ausearch -m AVC,USER_AVC -ts recent 2>/dev/null | tail -n 50
ResolutionRestore the distribution's directory ownership and security label or correct the documented container mount. Do not make the directory world-writable.
ERROR 2003 returns `Connection refused` immediately.
Likely causeNo process listens on the selected address and port, mysqld is loopback-only, the destination is wrong, or a firewall actively rejects the connection.
sudo ss -lntp 'sport = :{{dbPort}}'getent ahosts {{dbHost}}; nc -vz -w 3 {{dbHost}} {{dbPort}}
ResolutionCorrect the listener or destination proven wrong, then retest from the real source. Do not broaden the firewall before a listener exists.
ERROR 2003 takes several seconds and ends in a timeout.
Likely causeA packet is silently dropped by host, cloud, VPN, container, or network policy; the route is asymmetric; or DNS returned an unreachable address family.
ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}')nc -vz -w 3 {{dbHost}} {{dbPort}}
ResolutionUse route and flow evidence to change the narrow owning policy. Keep IPv4 and IPv6 DNS aligned with actual listeners.
Local TCP works on 127.0.0.1, but remote TCP is refused.
Likely cause`bind_address` is loopback-only or the service is intentionally local-only; firewall changes cannot extend a loopback listener.
sudo ss -lntp 'sport = :{{dbPort}}'sudo mysql --protocol=SOCKET --execute="SHOW VARIABLES WHERE Variable_name IN ('bind_address','skip_networking','port');"
ResolutionConfirm remote access is required, bind to the approved private address, validate, restart in a maintenance window, and keep the source-restricted firewall.
The port accepts TCP, but the MySQL client reports a TLS error.
Likely causeThe certificate is untrusted, expired, names another host, the client lacks the CA, or an intermediary presents a different identity.
getent ahosts {{dbHost}}mysql --host={{dbHost}} --port={{dbPort}} --ssl-mode=VERIFY_IDENTITY --ssl-ca={{caFile}} --user=connection_probe --password
ResolutionFix CA distribution, service naming, certificate issuance, or proxy routing. Preserve VERIFY_IDENTITY and never fall back to plaintext for diagnosis.
The failure is intermittent across clients.
Likely causeDNS returns mixed healthy and stale addresses, only one listener or firewall path is correct, or a load balancer includes an unhealthy backend.
getent ahosts {{dbHost}}for address in $(getent ahostsv4 {{dbHost}} | awk '{print $1}' | sort -u); do nc -vz -w 3 $address {{dbPort}}; done
ResolutionRemove or repair the specific stale endpoint through its owner, verify every address with TLS host identity, and observe a full resolver TTL window.
MySQL is healthy on the host, but a container cannot reach it.
Likely cause`localhost` points to the container, the Unix socket is not mounted, host routing differs, or container network policy blocks the private address.
getent ahosts {{dbHost}}; ip route get $(getent ahostsv4 {{dbHost}} | awk 'NR==1{print $1}')nc -vz -w 3 {{dbHost}} {{dbPort}}
ResolutionUse the documented service DNS/TCP endpoint or an intentionally mounted protected socket and update the container's owned policy; do not use host networking as a shortcut.
Reference
Frequently asked questions
What is the difference between MySQL ERROR 2002 and ERROR 2003?
ERROR 2002 commonly names a local Unix socket and means that path could not be opened, although local TCP misselection can also surface under connection errors. ERROR 2003 names a host and port and means the TCP connection could not be established. Preserve the exact message and operating-system number before choosing a branch.
Why does `mysql -h localhost` use a socket instead of TCP?
On Unix, MySQL clients normally treat `localhost` as the local Unix socket. Use `--protocol=TCP --host=127.0.0.1` for an explicit local TCP test and `--protocol=SOCKET --socket=...` for an explicit socket test.
Should I open port 3306 in the firewall first?
No. First prove that mysqld listens on the intended private address and port and that remote access is approved. Then permit only the exact reviewed source range through every policy layer.
Can a running mysqld process still produce ERROR 2003?
Yes. It may listen only on a Unix socket, have `skip_networking` enabled, bind to loopback or another address, use another port, run in a different namespace, or be blocked along the network path.
Why does the connection work from the database host but not the application?
The local test may use a socket or loopback listener, while the application uses DNS, routing, NAT, a container namespace, firewall policies, and remote TLS. Reproduce from the application boundary and compare the selected endpoint and source.
Can I disable TLS temporarily to isolate ERROR 2003?
No. A bounded TCP probe can test transport without credentials, and the MySQL client can then test `VERIFY_IDENTITY`. Disabling TLS changes the production security boundary and does not repair DNS, routing, or listeners.
When should I restart MySQL?
Only after evidence proves a non-dynamic startup setting or service failure is the cause, configuration validation passes, active workload impact is approved, and a protected rollback plus console path are ready.
Recovery
Rollback
Restore the captured MySQL option file, DNS record, firewall rules, and client endpoint separately for the changed layer; validate the old server configuration before restarting and prove the last known-good socket and private listener afterward.
- If only client configuration changed, restore the previous owned host, port, protocol, socket, and CA reference, then recycle only the affected application connections.
- If MySQL startup configuration changed, restore the protected option file, run `mysqld --validate-config`, restart through the maintenance path, and verify service state, socket, listener, server UUID, and logs.
- If a firewall or security-group rule changed, restore the prior ruleset atomically and verify that approved traffic returns while unapproved sources remain blocked.
- If DNS changed, restore the prior record, keep both endpoints monitored through at least one resolver TTL window, and verify certificate identity on every returned address.
- Record the rollback result with the original ERROR 2002/2003 reproduction, active endpoint evidence, application recovery state, and any remaining network uncertainty.
Evidence