Recovering from a Non-Primary Component
When wsrep_cluster_status reads non-Primary, a MariaDB Galera node has lost quorum and is refusing every write — and the recovery you choose in the next few minutes either restores service cleanly or splits your data forever. This guide, part of Automated Failover & Quorum Recovery in Galera, answers one precise question: exactly when and how do you promote a stuck non-Primary component back to Primary with pc.bootstrap, and when must you refuse to. It covers the symptoms you will actually see, the survivor-selection rule that prevents data loss, the runtime SET GLOBAL wsrep_provider_options='pc.bootstrap=YES' command, and the specific danger of reaching for pc.ignore_sb instead.
Context: Why a non-Primary Node Refuses Writes
A Galera group stays writable only while the members that can see each other hold a majority of the last-agreed weight — the surviving majority is the primary component, and any partition that finds itself in the minority transitions to non-Primary to make split-brain arithmetically impossible. That quorum arithmetic is developed in full in Understanding Galera Synchronous Replication; the operational consequence is that a non-Primary node fails every write with WSREP has not yet prepared node for application use and serves reads only if you explicitly allow them.
There are two distinct ways to arrive at non-Primary, and they demand opposite responses. In the first, a majority partition still exists somewhere — you are simply looking at the losing minority, which will rejoin on its own once connectivity heals. In the second, no partition holds a majority (a symmetric split, or a total outage where every survivor is a minority of the original weight), so no primary component exists at all and one must be reconstructed by hand. Bootstrapping in the first case is a catastrophe; bootstrapping the correct node in the second is the fix. The entire recovery hinges on telling them apart before you type anything.
Solution: Diagnose, Select the Survivor, then Bootstrap
Step 1 — Confirm you are actually non-Primary, and that nobody else is Primary
Check the status on every node you can still reach:
SHOW GLOBAL STATUS WHERE Variable_name IN
('wsrep_cluster_status', 'wsrep_cluster_size',
'wsrep_local_state_comment', 'wsrep_last_committed', 'wsrep_cluster_conf_id');
If any reachable node reports wsrep_cluster_status = Primary, stop — a writable component already exists, and your non-Primary node will rejoin it automatically once the network heals. Forcing a bootstrap now creates a second primary component and diverges the dataset. Only proceed when every reachable node reports non-Primary.
Step 2 — Select the survivor with the most complete state
The node you promote must be the one holding the highest committed sequence number, because its history is a superset of the others’ and promoting a laggard silently discards the transactions it never saw. Read each survivor’s true position from the running server or, if stopped, from the recovery path:
-- On each running non-Primary node
SHOW GLOBAL STATUS LIKE 'wsrep_last_committed';
# On a stopped node, derive the authoritative seqno (replays the InnoDB redo log)
mariadbd --wsrep-recover 2>&1 | grep 'Recovered position'
# → WSREP: Recovered position: 6f2a4b...:184230
Compare the sequence numbers across all survivors. The largest one is the node you bootstrap; every other node will discard its divergent tail and resync from it. Selecting the highest-seqno survivor is the same rule the full failover procedure applies after a total loss.
Step 3 — Promote the survivor with pc.bootstrap
Once you have confirmed no Primary exists and identified the highest-seqno node, promote that node only back to Primary at runtime — no restart required:
-- On the chosen highest-seqno survivor ONLY
SET GLOBAL wsrep_provider_options = 'pc.bootstrap=YES';
This tells the Galera provider to declare its current component the primary component. The node immediately becomes writable, its wsrep_cluster_status flips to Primary, and any other survivors that can see it re-evaluate quorum and rejoin — pulling the delta by Incremental State Transfer if gcache still holds it, or a full State Snapshot Transfer otherwise. Verify before routing traffic:
SHOW GLOBAL STATUS LIKE 'wsrep_cluster_status'; -- → Primary
SHOW GLOBAL STATUS LIKE 'wsrep_cluster_size'; -- climbs as peers rejoin
pc.bootstrap is the runtime counterpart to galera_new_cluster: use pc.bootstrap when the node is already running and stuck non-Primary, and galera_new_cluster when you are cold-starting a stopped survivor into a fresh component. Never issue pc.bootstrap on more than one node.
Parameter & Command Reference
| Item | Type | Default | Use it to | Danger |
|---|---|---|---|---|
pc.bootstrap=YES |
dynamic provider option | — | Promote a running non-Primary component to Primary in place | Promoting two components at once forks the data |
galera_new_cluster |
CLI wrapper (--wsrep-new-cluster) |
— | Cold-start a stopped survivor as a new primary component | Bootstrapping a non-highest-seqno node loses committed writes |
wsrep_last_committed |
status (integer) | — | Rank survivors to pick the one to promote | A non-Primary node still reports it; use it to compare, not to write |
wsrep_cluster_conf_id |
status (integer) | — | Detect two components: differing values = split view | Equal values do not by themselves prove quorum |
pc.recovery |
boolean | true |
Auto-restore the primary component after a full power loss via gvwstate.dat |
If false, a total outage always needs a manual bootstrap |
pc.ignore_sb |
boolean | false |
(Two-node designs only) keep a minority writable | Standing true on 3+ nodes permits real split-brain |
pc.ignore_quorum |
boolean | false |
Emergency: ignore quorum to force writability | Leaves no split-brain guard whatsoever; never a standing value |
Verification
After the bootstrap, prove the group genuinely reconverged into a single view rather than two:
-- Run on every node; all three checks must agree cluster-wide
SHOW GLOBAL STATUS WHERE Variable_name IN (
'wsrep_cluster_status', -- 'Primary' everywhere
'wsrep_cluster_size', -- equals the expected member count
'wsrep_cluster_conf_id', -- IDENTICAL on all nodes = one shared view
'wsrep_local_state_comment', -- 'Synced' everywhere
'wsrep_evs_state' -- 'OPERATIONAL'
);
The critical check is wsrep_cluster_conf_id: if two nodes report Primary but with different conf-ids, you have created exactly the split you were trying to avoid. A quick end-to-end proof is to write a sentinel row on the bootstrapped node and confirm it appears on every rejoined peer within a second. For a scripted gate that reads this surface and handles the 1213/1205 contention codes, reuse the controller in the failover and quorum-recovery guide or the Python probes in Monitoring Galera Cluster State with Python.
Edge Cases & Gotchas
pc.ignore_sb=trueis not a recovery tool — it is a split-brain switch. It is tempting when a two-node cluster wedges non-Primary after losing one node, because it makes the survivor writable instantly. But on any cluster of three or more it lets a partitioned minority keep accepting writes at the same time as the majority, and the two histories diverge with no automatic reconciliation. If you need a two-node deployment to survive one loss, add a Galera arbitrator with garbd as a third vote instead of disabling split-brain protection.- Bootstrapping the wrong survivor is silent.
pc.bootstrapwill happily promote a node whose seqno is behind a peer’s; there is no warning, and the higher-seqno peer’s extra transactions are discarded when it resyncs downward. Always comparewsrep_last_committed(or--wsrep-recoveroutput) across every survivor first — the comparison is the safety mechanism, not the command. - Two accidental bootstraps fork the Galera cluster. If two operators each promote a different node, or automation fires
pc.bootstrapon more than one, you get two Primary components with differentwsrep_cluster_conf_idvalues and divergent data. Recovery then means picking one component as truth, dumping any writes that landed on the other, and re-SST-ing its nodes. Serialize bootstrap authority to a single actor.
Related
- Automated Failover & Quorum Recovery in Galera — the full failover procedure and the Python supervisor this decision plugs into
- Configuring a Galera Arbitrator with garbd — add a tie-breaking vote so a minority never wedges non-Primary
- Understanding Galera Synchronous Replication — the quorum and certification model behind primary-component logic
- Handling Galera Startup Errors & Logs — reading the provider log lines a bootstrap emits