Feature #684: In-memory Relaylog - #743
Conversation
|
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. If you are an Oracle employee, please make sure that you are a member of the main Oracle GitHub organization, and your membership in this organization is public. |
- Primary issue: mysql#684 - Design: `design/replication/684-in-memory-relaylog`
NOTE: This is a test level commit for high level design proposal. What's implemented in this commit: 1. Add IMR CRST command with configurations. 2. Implement end-to-end memory-path relaylog. 3. Implement end-to-end spill-path for large transaction. 4. Add IO/SQL thread recovery (single thread stop/start) 5. Add unittests for introduced class/functions. 6. Add end to end MTR tests.
f826ea3 to
ca86326
Compare
|
|
||
| ER_BULK_READER_PATH_IS_DIRECTORY | ||
| eng "Bulk Reader: Path is a directory, expected a file: %s" | ||
| ER_CRST_IN_MEMORY_RELAYLOG_ONLY_FOR_CSA |
There was a problem hiding this comment.
There is merge conflicts on this file, please resolve
|
To whom it may concern, the published code change in this PR is for demonstration and testing only.
The code is for validation and map the design to the code. More changes may be submitted in the following development process. |
|
Thank you for signing the OCA. |
karolina-szczepankiewicz
left a comment
There was a problem hiding this comment.
The design is in good shape. I reviewed the design and used the provided code only for validation. I requested clarification where the implementation and design diverge. I recommend resolving some comments through discussion, but most can be addressed during implementation and code review. Thank you!
| assert(m_fde_ptr != nullptr); | ||
| } | ||
|
|
||
| Cached_event_payload::~Cached_event_payload() { |
There was a problem hiding this comment.
Great. Would you like to report this as a bug and submit the fix as a separate contribution / a separate PR?
| | ---------- | -----------------: | ------------------------------: | | ||
| | Receiver | 80 | 230 | | ||
| | Applier | 66 | 67 | | ||
| | End-to-end | 44 | 65 | |
There was a problem hiding this comment.
Great improvement!
| The coordinator consumes transactions through the existing `Transaction_provider` interface, so the `Csa_service::run` loop, scheduler, dependency tracking, and worker pool are all reused unchanged. The changes on the coordinator side are limited to the `Reader` interface. | ||
| A new reader `Queued_transaction_reader` is introduced as a memory path counterpart of `Relay_log_adaptive_reader`. Its `read()` takes the envelope at `dispatch_seqno` from the `Trx_envelope_queue`, advances the cursor, and wraps the envelope's `Fetchable_transaction` into a fresh `Job_applier` using the same constructor the relaylog reader uses today. | ||
| Everything downstream is untouched. The coordinator obtains the next transaction from the provider, computes scheduling dependencies from the logical clock and commit-order inputs, and dispatches it to the worker thread pool exactly as today. | ||
| The coordinator also tries to advance `commit_seqno` in the queue over a contiguous run of committed transactions at the head and dequeues each. A transaction that commits behind an uncommitted head is only marked committed and swept later when the head commits. |
There was a problem hiding this comment.
I had a comment about the previous approach, but you changed it to lazy advancement of the commit LWM by the coordinator, which is great. The only remaining item is a short explanation of why the queue maintains a committed prefix separately from the CSA scheduler's existing Clock_lwm_registry, which also computes a contiguous completed task prefix regardless of the value of replica_preserve_commit_order.
| @@ -0,0 +1,81 @@ | |||
| ### Functional Requirements | |||
|
|
|||
| - FR1. The feature must provide a per-channel option, introduced as a new `CHANGE REPLICATION SOURCE TO` option `IN_MEMORY_RELAYLOG_ENABLED`, that controls whether the feature is enabled. It is `ON` by default for eligible channels. When `OFF`, replication must fall back to the standard disk path relaylog. | |||
There was a problem hiding this comment.
The implementation defaults IN_MEMORY_RELAYLOG_ENABLED to OFF. Please update the design to use OFF consistently. With this default, IMR is enabled only through an explicit CHANGE REPLICATION SOURCE TO statement, and no separate default is needed for upgraded channels.
There was a problem hiding this comment.
IMHO we should keep the default as OFF, given that users expect durability of relay logs by default.
User stories on 667fcff#diff-8bcbe8983b9d223e1cb768c4a672500fb8844b4b9e8638d6d8fb1023d6fef248 also need to be updated.
| - FR38. An error diagnostic file created by the feature must have a name matching the pattern `imr_err_<channel>_<unique_id>`, where `<channel>` is a lowercase channel identifier and `<unique_id>` is a lowercase identifier unique within `#in_memory_relaylog_temp_files` (imr_err stands for "In-Memory Relaylog Error"). | ||
| - FR39. Startup cleanup must not delete temp error diagnostic files, contrary to FR25. | ||
| - FR40. If the feature encounters a non-recoverable error, the user must be able to fall back to the standard disk path relaylog and resume replication without data loss by stopping the channel, setting `CHANGE REPLICATION SOURCE TO` with `IN_MEMORY_RELAYLOG_ENABLED = OFF`, and restarting it. | ||
|
|
There was a problem hiding this comment.
It's good that FR30-FR30.2 now cover the partial transaction on STOP REPLICA IO_THREAD. The remaining thing is disabling IMR through CRST. Please add one functional requirement stating that the threads must be stopped, the IMR queue is removed, and the next start uses the disk relay log. Please also state what happens to spill and diagnostic files.
|
|
||
| ### Configuration / Knobs — New configuration clauses or options | ||
|
|
||
| All In-Memory relaylog settings are per channel. They are exposed as `CHANGE REPLICATION SOURCE TO` clauses. Each clause is a per-channel value held in the channel's in-memory `Master_info` and backed by the persisted replication metadata repository. They are effective only on a CSA channel with asynchronous replication. Setting them on any other channel type is rejected with an error. |
There was a problem hiding this comment.
Please change Master_info to Relay_log_info in this paragraph
| Recovery | ||
|
|
||
| The queue is purely an in-memory struct that cannot persist through replication stop, server restart, or crash. The recovery process therefore relies only on the durably recorded `gtid_executed`. Any uncommitted transaction can be re-obtained by GTID, either re-dispatched from the queue if it still holds the transaction (in the case of `STOP REPLICA SQL_THREAD`), or re-fetched from the source by auto-positioning. Duplicates are harmless because a worker skips any transaction whose GTID is already in `gtid_executed` (`is_already_logged_transaction`), and an interrupted transaction is always rolled back and re-fetched during recovery. | ||
| `STOP REPLICA SQL_THREAD` (applier only; receiver keeps running). The queue and all uncommitted envelopes still stay in memory. In-flight jobs are driven to a terminal state (commit, or roll back), so no transaction is left half-applied. With no advance of `commit_seqno`, all uncommitted transactions remain in the queue. The IO thread keeps enqueuing new envelopes until the memory usage counter reaches the `IN_MEMORY_RELAYLOG_LIMIT`. On next `START REPLICA SQL_THREAD`, the coordinator rewinds `dispatch_seqno` to `commit_seqno` and re-dispatches all the retained uncommitted transactions in order; committed-but-not-yet-swept envelopes are skipped because their payload is freed. |
There was a problem hiding this comment.
The implementation performs one final sweep_committed() after the SQL thread and workers stop. Please change this paragraph if applicable.
|
|
||
| In-memory relaylog keeps the transaction in memory instead. As a new transaction arrives, the receiver wraps the transaction metadata and incoming encoded events into a data structure, pushes it to an in-memory queue. The coordinator reads from it and dispatches the transaction to workers, without relaylog file write/read during the process (referred to as the memory path in the document). | ||
|
|
||
| The queue has a hard memory limit per channel. A transaction larger than a configured threshold is re-routed to a temporary file in standard relaylog format (referred to as the spill path in the document). On replication stop, server restart, or crash, the queue is emptied and any uncommitted transactions are re-fetched by GTID auto-positioning. |
There was a problem hiding this comment.
Please change On replica stop to On full replication channel stop
|
|
||
| **NAME**: `IN_MEMORY_RELAYLOG_LIMIT` | ||
|
|
||
| **VALUES:** unsigned integer, bytes. Range [33554432 (32 MB), 4294967296 (4 GB)]; values outside the range are rejected. |
There was a problem hiding this comment.
Please note that this range will require a 64 bit integer. If you would like to keep a 32 bit value, please change the maximum to 4 GiB - 1.
|
|
||
| `SHOW RELAYLOG EVENTS` is not applicable | ||
|
|
||
| `FLUSH RELAY LOGS` is a no-op. |
There was a problem hiding this comment.
Please note that the implementation must block standard relay log rotation to keep this operation a no-op.
| otherwise -> block until commits free space, then memory path | ||
| ``` | ||
|
|
||
| Reserving the exact `trx_length` up front guarantees a memory-path transaction fits before streaming begins. A transaction larger than the `IN_MEMORY_RELAYLOG_SPILL_THRESHOLD` always takes the spill path. |
There was a problem hiding this comment.
It would be good to list the reasons to have both IN_MEMORY_RELAYLOG_SPILL_THRESHOLD and IN_MEMORY_RELAYLOG_LIMIT.
nacarvalho
left a comment
There was a problem hiding this comment.
Thank you for the contribution.
I only looked into the design, please see my comments inline.
|
|
||
| **Out of Scope / Limitations** | ||
|
|
||
| The feature is effective only on CSA channels. It is not supported for `Group Replication` channels, or `Semisynchronous` replication. Enabling this feature on such channels shall be rejected. |
There was a problem hiding this comment.
Need to be clarified that for Group Replication, only group_replication_applier channel cannot enable it.
group_replication_recovery channel can enable it, same way it can enable CSA.
This also impacts FR2.
design/replication/684-in-memory-relaylogWhat does this change do?
Why is it needed?
How was it tested?
mysql-test/scripts/ci/mtr.shpasses locallyrpl,rpl_nogtid,rpl_gtid.Contributor checklist
scripts/ci/format.sh)AI assistance
If AI assistance was used, describe the tool(s) and extent of use:
AI is used for
Areas touched
replication