16. Known limitations
This page lists, honestly and up to date, what is not available in this version of MIRAJ. Each item was checked directly against the engine code rather than copied from earlier documentation: several features long announced as missing are in fact already shipped (see the closing note at the end of this page), and this page reflects that.
For quantified limits (maximum sizes, type ranges, number of threads, etc.), see the chapter on sizing limits; this page covers missing features, with an alternative where one exists.
1. Transactions and concurrency#
| Missing feature | Current situation | Alternative / workaround |
|---|---|---|
Fully functional SAVEPOINT | SAVEPOINT name alone is accepted with no effect; ROLLBACK TO SAVEPOINT and RELEASE SAVEPOINT return an error (feature not supported) | Split the transaction into smaller units, or handle partial retry on the application side |
XA (two-phase distributed transactions) | Not recognized | No alternative in this version; planned for a later version for multi-resource scenarios |
| Isolation levels below SERIALIZABLE | SET TRANSACTION ISOLATION LEVEL is remembered but has no effect: every read of a transaction that writes is validated at its COMMIT. With deferred update (chapter 9, §9.2), a transaction that reads a row and then updates it therefore receives 1213 at COMMIT if another transaction modified that row in the meantime | Put the condition in the UPDATE itself (… WHERE id = 7 AND qte >= 1) rather than reading the row first; otherwise, replay the transaction |
MIRAJ uses optimistic multiversion control with serializable isolation: readers are never blocked or cancelled, and a transaction never waits for a row lock (it fails immediately and must be retried). This is a fundamental difference from a classic pessimistic-locking engine, described in detail in docs/concurrency.md — it is not a limitation but an architectural choice to be aware of when writing code that retries its transactions correctly. Deferred update (enabled by default) avoids this 1213 for UPDATEs of a row designated by its key, which are recomputed at COMMIT; in return, a computation error (1264, 1048, 4025…) or a conflict may only appear at COMMIT, which then rolls back the whole transaction.
2. SQL: what is really missing#
Contrary to what older product documentation may have suggested, most of the advanced SQL constructs listed below are already supported in this version. Only the following are still missing:
| Missing feature | Current situation | Alternative / workaround |
|---|---|---|
WITH RECURSIVE (recursive CTE) | A non-recursive table expression (WITH name AS (...)) is supported; the recursive form is not | Unroll the recursion on the application side, or use a stored procedure with a loop |
NATURAL JOIN | Recognized by the parser but rejected at execution (feature not supported) | Write the join condition explicitly with ON or USING |
FULL [OUTER] JOIN | Not recognized | Combine a LEFT JOIN and a RIGHT JOIN with UNION |
Correlated subquery in the ON condition of a join, or in the ORDER BY of a UNION | Error reported | Rewrite the condition without correlation in that specific place (the same correlated subquery remains possible elsewhere in the query) |
INTERSECT / EXCEPT | Not recognized | Rewrite with NOT EXISTS / EXISTS or a join |
Sequences (CREATE SEQUENCE) | Not supported | Use an AUTO_INCREMENT column |
Secondary indexes by column range or prefix (col(n) in an INDEX) | Secondary indexes themselves are supported (see below), but only for an exact equality on all of their columns; never for a range, an IN, or a prefix | Create a generated column that isolates the useful part of the value, and index it |
Inverted indexes / vector index for VEC_DISTANCE | Vector search (VECTOR(n), distances) works, but without a dedicated index: ORDER BY distance LIMIT k computes an exact k-nearest-neighbors (spread over several threads), not an index-based approximate search | Accept the cost of an exact scan, sized by LIMIT |
No longer limitations (contrary to older product documentation, which is not intended for the public): subqueries (uncorrelated and correlated, except the two places cited above), UNION/UNION ALL, RIGHT JOIN, INSERT ... SELECT, REPLACE, INSERT ... ON DUPLICATE KEY UPDATE, non-unique secondary indexes, EXPLAIN, window functions (OVER (PARTITION BY ... ORDER BY ...)) and non-recursive table expressions (CTEs) are implemented in this version. See the note at the end of the page.
3. Connections and security#
| Missing feature | Current situation | Alternative / workaround |
|---|---|---|
| Encryption of data at rest | Not implemented: table files (.mrj, .bmrj) are not encrypted on disk | Encrypt at the file system or disk level (BitLocker, LUKS...) if needed |
Column-level privileges (GRANT SELECT (col1, col2) ON ...) | Not supported; access control stops at the table level | Restrict access through a view that projects only the authorized columns |
Routine-level privileges (GRANT EXECUTE ON PROCEDURE ...) | Not supported: only the global EXECUTE privilege exists | — |
PROXY (proxy users) | Not recognized | — |
RENAME USER | Not recognized | Recreate the account under the new name and carry over its privileges with GRANT |
Per-account resource limits (GRANT ... WITH MAX_QUERIES_PER_HOUR ...) | Not supported | Handle throttling on the application side or in a network proxy |
No longer limitations: TLS for client connections is available (--tls-cert, --tls-key, --require-tls, TLS 1.2 and 1.3) — this is a feature distinct from the mutual TLS used between nodes of a replication cluster (see §5), and the two must not be confused: one encrypts the client ↔ server link, the other encrypts the link between cluster nodes and authenticates each node by a certificate signed by the cluster authority. KILL and KILL QUERY are also available, as are roles and per-database and per-table privileges.
4. Data types#
| Missing feature | Current situation | Alternative / workaround |
|---|---|---|
BIGINT UNSIGNED beyond 2^63 − 1 | The column is stored internally on a signed 64-bit integer: values between 2^63 and 2^64 − 1 (although valid for this type) are rejected on write | Use DECIMAL for positive values exceeding 2^63 − 1 |
5. Replication and cluster (Cluster edition)#
Multi-node replication is implemented in this version: a primary node accepts writes, an unlimited number of secondary nodes replicate the log continuously and remain available for read-only queries (Cluster edition), and the link between nodes is encrypted with mutual TLS using a certificate specific to each node for authentication. This corrects older documentation that presented replication as absent or insufficiently described.
Current limitations of this feature:
| Missing feature | Current situation | Alternative / workaround |
|---|---|---|
| Automatic failover (election of a new primary) | In manual mode (default), promotion is manual and controlled (refusal 9003). In raft mode (mode = "raft", chapter 12, §12.9), the primary is elected by a majority of the members; limitations of this first increment: fixed membership, non-linearizable reads, OFF writes of an isolated leader lost (quarantine), possible blocked election (database absent on the survivors), deleted database reappearing if an absent node is elected | Raft mode with MAJORITY for writes that must not be lost; 'force_primary' as a last resort when the majority is lost |
| Distributed queries across nodes | Each node answers with its own data; there is no query federation between nodes | Send queries to the appropriate node from the application |
| Fully synchronous replication (write invisible until acknowledged), quorum | Replication is asynchronous by default; semi-synchronous replication (@@cluster_sync_commit = RECEIVED | APPLIED, chapter 12, §12.8) makes a write wait for the acknowledgments of cluster_sync_replicas secondaries, but the write is committed and visible on the primary before these acknowledgments, and an exceeded timeout confirms it with a warning 9004 (or an error 9004, the write remaining committed); the MAJORITY level (written to a majority of members) and election exist in raft mode (§12.9) | For writes that must not be lost at failover: SET SESSION cluster_sync_commit = 'received' with cluster_sync_timeout_action = 'error' (or 'wait'), and treat error 9004 as an unknown result to be verified |
6. Where to find technical details#
For a complete, quantified inventory (sizes, ranges, precise column-by-column behaviors, including those not listed here because they are not limitations but characteristics of the engine), consulting the engine source code remains the most up-to-date reference; this page is limited to features that are concretely missing for everyday use.
7. Outlook: future developments#
Some of the limitations above are expected to disappear in later versions of MIRAJ, following a multi-stage roadmap that notably covers:
- an even higher-performance storage engine for analytics (advanced compression, SIMD vectorized computation, cost-based optimizer);
- additional server features (incremental or compressed backups — full hot backup exists, see chapter 18 —, encryption of data at rest, extended monitoring);
- an evolution of high availability (automatic failover, distributed queries).
These developments are given as an indication of the product trajectory and do not constitute a commitment to a schedule.
Note on this page: several items listed as missing in earlier product documentation turned out, upon direct verification of the code, to be already implemented — in particular subqueries, UNION, RIGHT JOIN, INSERT ... SELECT, REPLACE, ON DUPLICATE KEY UPDATE, TLS for client connections, KILL QUERY, non-unique secondary indexes, EXPLAIN, window functions, table expressions (non-recursive CTEs), as well as cluster replication with mutual TLS between nodes and stored procedures/functions. This page has been corrected accordingly.