Replication
HardhatDB replicates with Raft. There is one leader. Followers apply the same log and can serve reads that are behind the commit index.
Writes
A write on the leader commits through Raft, then returns. A write on a follower is forwarded to the current leader. An explicit transaction is forwarded as a whole. A read on a node waits until that node has applied its commit index, so another connection on the same node sees the write. A different node can still be behind by one Raft heartbeat. HARDHATDB_READ_FROM=leader forwards ordinary reads to the leader instead.
Row and table locks exist only on the process that executes the statement. SELECT ... FOR UPDATE and a SERIALIZABLE read run on the leader, so they meet the locks taken by writes. BEGIN sends the session's transaction_isolation with the transaction. A follower does not lock rows for those statements.
SHOW RAFT STATUS returns one row: role, leader, commit_index, applied_index, lag, and suffrage. On a follower the statement runs locally, so lag is how far that node is behind the commit index. suffrage is voter, nonvoter, or staging, and it is empty on a standalone process.
Binlog
Every node writes a binlog beside the Raft directory. HARDHATDB_SERVER_UUID is shared by the group and is the GTID server id. HARDHATDB_BINLOG_MAX_SIZE rolls the binlog after a transaction crosses that many bytes. The default is 1 GiB.
FLUSH BINARY LOGS on the leader rolls every node's binlog together. Any node can stream that binlog. After a promotion the GTID stream is the same.
Upstream MySQL
Set the same source on every node and the current primary replicates from it. A follower does not open the upstream connection. After a failover the new primary continues from the GTID stored with the applied rows.
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = 'mysql.example',
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'secret',
SOURCE_AUTO_POSITION = 1;
START REPLICA;SOURCE_AUTO_POSITION cannot be turned off. STOP REPLICA stops the job. The password is stored in a local file beside the Raft directory, so a promoted node can dial only if it already has that password. REPLICATE_REWRITE_DB is rejected.
The same values can be set in the environment before the first start: HARDHATDB_SOURCE_HOST, HARDHATDB_SOURCE_PORT, HARDHATDB_SOURCE_USER, and HARDHATDB_SOURCE_PASSWORD.
Moving an existing MySQL database, including when a dump is the right path, is in Migration.
Membership
Membership changes are leader statements. A follower forwards them.
RAFT ADD VOTER 'n4' '10.116.0.5:7001';
RAFT ADD NONVOTER 'n4' '10.116.0.5:7001';
RAFT REMOVE SERVER 'n4';Start the new process with the same peers and certificate names, then add it. A nonvoter copies the log and serves MySQL reads. It does not vote, so quorum stays the voters. Clients add that MySQL address for reads. A write sent there is still forwarded to the leader. A read on another connection can lag. RAFT REMOVE SERVER drops a voter or a nonvoter.
Writes still commit on the leader. A faster machine and volume for the voters raises that ceiling. A table whose writes do not fit that leader is placed with SHARD TABLE on a second set of peers. A size-based split stays on the current hosts and does not add a machine.
HARDHATDB_RAFT_BOOTSTRAP=1 bootstraps only when the Raft directory has no state and every other peer reports that it has none either. A later start with the flag still set logs that bootstrap is ignored, then catches up as a follower. A wiped volume with the flag left on refuses to start when a peer already has the group, unless HARDHATDB_RAFT_BOOTSTRAP_FORCE=1.