Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41825: SIGSEGV in THD::sp_fix_func_item when a ROW variable's DEFAULT is an EXISTS subquery Analysis: The check blocked non-ROW_RESULT subselects with single field. This eventually resulted in crash in absence of fields in the virtual_tmp_table. Fix: Disallow single-field subselect whose result type is non-row result and throw error. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aria: ma_commit() flushes the log up to an uninitialized LSN If translog_write_record() failed for the COMMIT record, ma_commit() still called translog_flush(commit_lsn), with commit_lsn not initialized. The | operator was there so that trnman_commit_trn() is always called; that call is a separate statement since 91bc9cc9e66. Call translog_flush() only if the COMMIT record was written, as the other callers of translog_write_record() do. Under Valgrind, maria.aria_log_create_error reports the uninitialized value without this change. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch 'bb-11.8-release' into bb-12.3-release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Khaled Riyad
khaled57.dev@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41470 Server crashes in check_grant / delete_precheck on 2nd execution of SP When a procedure changes a view that calls a stored function, the tables of that function are added to the statement's table list for prelocking. From the second call on, they are already in the list when the privilege precheck runs. `check_one_table_access()` took the first of them for a table of the view, and the check then walked past the end of the list and crashed. Stop in `check_one_table_access()` when no tables owned by the statement are left. The prelocking tables are checked when their routines run. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41564: Make optimizer context replay warnings translatable Replace ER_JSON_OPTIMIZER_REPLAY_CONTEXT_MATCH_FAILED, which took hard-coded English fragments as arguments, with six specific messages (table, index, range context, ranges, cost_for_index_read_calls, records_in_range_calls) that have their own format strings and Spanish translations. Also fix format specifiers: print ha_rows with %llu and the parse error offset with %lld. Add tests that replay each mismatch under lc_messages=es_ES. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41585 Wrong result with multi-table UPDATE with ORDER BY When ORDER BY makes the join of a multi-table UPDATE resolve via a temporary table, the join first writes all its rows to that table and then, after sorting, reads them back and calls multi_update::send_data() for each. MDEV-14551 made the rowids of the updated tables travel through the join temp table (JOIN::add_fields_for_current_rowid() and multi_update::prepare2()), but the SET values did not. The select list of the join for the below SQL is empty, so send_data() evaluates it with fill_record() against the tables' record buffers, which by then hold the last row read during the join. Every updated row got the value computed from that one row, e.g. UPDATE t1, t2 SET t2.v = t2.v + 1 ORDER BY t1.id set all rows of t2 to the same value (as long as the ORDER BY is not optimized away). multi_update::initialize_tables() now adds the non-constant SET values to JOIN::all_fields as hidden fields, the same way ORDER BY items and the rowids are added, so they are computed into the join temp table while the rows they read are current. It records the ref_ptrs slot of each value in multi_update::value_slots[], and multi_update::prepare2() replaces each value in values_for_table[] with the temp table item in the same slot of the temp table's ref array. Recording the slot at push time means prepare2() does not depend on const_item() giving the same answer at optimization and at execution, and does nothing when the values were not pushed. The hidden fields need ref_ptrs slots. st_select_lex::get_cardinality_of_ref_ptrs_slice() now reserves item_list.elements more for the top-level select of an UPDATE. This includes single-table UPDATE, because a prepared single-table UPDATE can allocate the ref array on its first execution and run as a multi-table UPDATE on a later one. A consequence is that the SET values are now evaluated once per join row written to the temp table, before LIMIT applies, instead of once per updated row. For a value with side effects, such as NEXTVAL(), an UPDATE with ORDER BY and LIMIT consumes one value per join row. The test records this. This commit was prepared with Claude Code (Opus 5.5), which analyzed the problem, explored, presented possible fixes and implemented the chosen one. Claude Code (Fable 5.1) reviewed the result, replaced the items0[] pointer scan in prepare2() with the recorded slots, and added the NEXTVAL test case. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria log rotation before the end of the backup log backup.backup_aria_log_rotate: after BACKUP SERVER copied the table files, commits to a table that is safe for online backup continue until BACKUP_LOCK_COMMIT and make the log continue in at least two new files. The backup ends in the same log file as the server, and recovery of the backup applies these commits from the start checkpoint, over the whole log files, to the copied table files. The test fails when the log files before the file of the end are not copied. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aria: double free after a failed log file creation translog_create_new_file() adds the new TRANSLOG_FILE to log_descriptor.open_files before it creates the file. If the creation failed, the error path freed the object but left the pointer in open_files. If translog_write_file_header() or ma_control_file_write_and_force() failed, the error path freed the object that open_files already owned. In both cases, translog_destroy() closed and freed the object again at shutdown: "Error on close of '(null)'", followed by heap corruption. Remove the pointer from open_files if the file creation fails. Do not free the object after open_files owns it. The test needs a non-debug build, because translog_stop_writing() fails a debug assertion. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yuchen Pei
ycp@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40808 Zero the new tmp TABLE_LIST struct in close_cached_connection_tables_callback Otherwise garbage non-NULL view field would result in garbage view_db field returned in get_db_name which would cause crash in Lex_ident_fs::check_db_name(). If we simply initialise a NULL view field, the garbage non-NULL derived field would cause the tables->is_anonymous_derived_table() to return true and skip the tmp table created in close_cached_connection_tables_callback so the open HANDLER is not closed and `tdc_remove_table()` waits forever for the session's own reference. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria UPDATE after BACKUP SERVER copied the log The new DEBUG_SYNC point maria_backup_log_copied stops BACKUP SERVER after the Aria log was copied under BACKUP_LOCK_COMMIT. An UPDATE on a TRANSACTIONAL=1 Aria table then changes all rows, and its commit waits for the backup. With a small page cache, the UPDATE evicts and writes data pages whose LSN is after the end of the copied log. If the data files are copied after the log, the backup holds those pages, and the table is corrupted after recovery of the backup. Now the backup must hold the table as it was before the UPDATE. Test case by Marko Mäkelä. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38347 Debugging functions Extend current dbug_print* functions in such a way as to facilitate easy high level debugging. Introduce a single overloaded print function defined in dbp.h, DBUG_PRINT_FUNCTION, settable to your preference. Allow a shell environment variable DBUG_PRINT_FUNCTION to override this definition. Some functions written by Claude (Opus 5.5). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '12.3' into bb-12.3-release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sjaakola
seppo.jaakola@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38981 Galera loses wsrep_gtid_domain_id after pc.recovery restart Fix for MDEV-24546 changed the storage for wsrep_gtid_domain_id (either in config file or as an option) to be into wsrep_gtid_domain_id variable. And it is copied to wsrep_gtid_server struct's domain_id only in the variable's ON_UPDATE hookw. On server startup this struct was set only by the bootstrap (startup with --wsrep-new-cluster) or by SST/IST donation from the donor. When all nodes crashed and the cluster re-formed through pc.recovery, neither of these happened, so wsrep_init_gtid() replaced the recovered domain with 0. New writes then got domain 0. And afer this, later joiners also inherited domain 0 from their donor. The fix here is simply to copy wsrep_gtid_domain_id to wsrep_gtid_server struct in wsrep_init_server(), before any state transfer. Commit has a new mtr test: galera.MDEV-38981, Assisted-by: https://mariadb.org/governance/governance-ai-policy/ |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
nada
nadaelsayed163@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38829: Fix semisync assertion on failed direct binlog write MYSQL_BIN_LOG::write() guarded semisync registration (report_binlog_update) on the direct-write path with if (!error), but did not apply the same guard to the subsequent wait_after_sync() call. When the write failed before registering the transaction, wait_after_sync() still ran and looked for the transaction in the Active_tranx list, found nothing, and tripped the DBUG_ASSERT in commit_trx() that assumes a missing entry can only be caused by semisync having been switched off and on. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-22992 Refactor VIO into layered transports and filters Replace the function-pointer VIO implementation with an abstract C++ interface while retaining the procedural C entry points. Implement socket and named-pipe transports and composable filters for client read-ahead, Windows thread-pool prefetch, and TLS. OpenSSL uses a custom BIO, while wolfSSL uses callbacks that perform I/O through the VIO below the TLS filter. This keeps waits and timeouts in the transport layer. Keep sockets nonblocking and implement timed I/O with transport waits. Named pipes use overlapped I/O for timeout-aware waits and report blocking waits through the same scheduler callbacks as sockets. Semi-sync temporarily changes the real VIO read timeout instead of copying VIO state. Hide transport and TLS implementation state behind accessors. Expose the TLS handle opaquely and update callers that previously accessed VIO fields directly. Compile the VIO implementations as C++ and retain PSI memory accounting for VIO allocations. Adapt Windows thread-pool pre-read to a Prefetched_vio filter inserted above the transport so both plain and TLS connections consume prefetched bytes through the same layered VIO path. Clean header files so that vio headers no longer include OpenSSL or wolfSSL headers. Remove some legacy functionality: - vio_close() with its double-close guards appeared hard to maintain in the class hierarchy, and had been unnecessary for the last 15 years -- we consistently have used vio_shutdown() for waking up threads stuck in network IO. Associated things that are also gone: preprocessor definition SIGNAL_WITH_VIO_CLOSE (always defined), VIO_STATE_CLOSED. The VIO_CLOSED type, which was used as a sentinel, was renamed to VIO_TYPE_INVALID. - vio_io_wait() used in a single place, replaced by read with timeout. - vio_reset() to create SSL, replaced by vio_wrap. Assisted-by: Claude:claude-sonnet-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41585 Wrong result with multi-table UPDATE with ORDER BY When ORDER BY makes the join of a multi-table UPDATE resolve via a temporary table, the join first writes all its rows to that table and then, after sorting, reads them back and calls multi_update::send_data() for each. MDEV-14551 made the rowids of the updated tables travel through the join temp table (JOIN::add_fields_for_current_rowid() and multi_update::prepare2()), but the SET values did not. The select list of the join for the below SQL is empty, so send_data() evaluates it with fill_record() against the tables' record buffers, which by then hold the last row read during the join. Every updated row got the value computed from that one row, e.g. UPDATE t1, t2 SET t2.v = t2.v + 1 ORDER BY t1.id set all rows of t2 to the same value (as long as the ORDER BY is not optimized away). multi_update::initialize_tables() now adds the non-constant SET values to JOIN::all_fields as hidden fields, the same way ORDER BY items and the rowids are added, so they are computed into the join temp table while the rows they read are current. It records the ref_ptrs slot of each value in multi_update::value_slots[], and multi_update::prepare2() replaces each value in values_for_table[] with the temp table item in the same slot of the temp table's ref array. Recording the slot at push time means prepare2() does not depend on const_item() giving the same answer at optimization and at execution, and does nothing when the values were not pushed. The hidden fields need ref_ptrs slots. st_select_lex::get_cardinality_of_ref_ptrs_slice() now reserves item_list.elements more for the top-level select of an UPDATE. This includes single-table UPDATE, because a prepared single-table UPDATE can allocate the ref array on its first execution and run as a multi-table UPDATE on a later one. A consequence is that the SET values are now evaluated once per join row written to the temp table, before LIMIT applies, instead of once per updated row. For a value with side effects, such as NEXTVAL(), an UPDATE with ORDER BY and LIMIT consumes one value per join row. The test records this. This commit was prepared with Claude Code (Opus 5.5), which analyzed the problem, explored, presented possible fixes and implemented the chosen one. Claude Code (Fable 5.1) reviewed the result, replaced the items0[] pointer scan in prepare2() with the recorded slots, and added the NEXTVAL test case. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yuchen Pei
ycp@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41351 Allow a covering index scan for a SELECT ... FOR UPDATE under a full-scan table lock MDEV-24813 introduced a switch innodb_table_lock_on_full_scan that requests a table lock on an innodb table for some unconditional SELECT/UPDATE/DELETE statements. With a full table lock, and when doing a covering scan, there is no need to request clustered index reads. This patch does so for X-locks in SELECT statements. Prior to this it is already the case for S-locks. There is one exception: we disable this optimization when inside a transaction with innodb_snapshot_isolation and a read view already open, in which case it needs trx_id obtained from the clustered index to check if there is a committed change the transaction never saw. Assisted-By: Claude Opus 5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria inserts during BACKUP SERVER, no debug needed backup.backup_aria_concurrent_insert: BACKUP SERVER runs while another connection commits one row at a time to an Aria table that is safe for online backup, with a small page cache and small log files. The restored table passes CHECK TABLE EXTENDED and holds the rows 1..N with no gap, with N not more than the rows after BACKUP SERVER returned. The test uses no DEBUG_SYNC or DBUG keywords, so it also covers release builds, where the Aria log pages have no checksum. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: end the Aria log after the table copy The Aria log was copied at the start of BACKUP_LOCK_COMMIT, while commits were blocked, and before the deferred mysql tables were copied. Its end was the horizon at that time. maria_backup_end(BACKUP_LOCK_COMMIT) now determines the end of the log in the backup (maria_backup_context::end_lsn), after all table files were copied, and flushes the log up to it. Commits are blocked only for this. maria_backup_start(BACKUP_FINISHED) copies the log after the locks were released: the files before the file of the end as a whole, and the last file up to the page of the end. The log continues to grow after the end. The pages before the page of the end do not change. translog_cut_page() changes the page of the end to the page that translog_flush() wrote when the end was the horizon: the bytes from the end are filled with TRANSLOG_FILLER, and the page checksum is computed again. A page with sector protection is rejected; the server does not write it (TRANSLOG_DEFAULT_FLAGS). No log rotation is needed. backup.backup_aria_log_end replaces backup.backup_aria_write_after_log_copy. After the end of the log, an UPDATE writes log records and data pages while its commit waits for the backup lock. Before the log is copied, the UPDATE commits and more writes make the log continue in a new file. The backup contains none of these changes, ends in the log file of the end, and the restored server continues the log from the cut page after a kill. If the end is taken at BACKUP_FINISHED instead, the test fails. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: copy offline Aria tables before LOCK_COMMIT Aria tables that are not safe for online backup (TRANSACTIONAL=0, or without PAGE_CHECKSUM) were copied at BACKUP_LOCK_COMMIT. A large table of this kind blocked all commits during its copy. For a table outside the mysql schema, writes are blocked from BACKUP_FLUSH on (MDL_BACKUP_DML), and backup_block_ddl() waits for the running statements and flushes the open tables (flush_tables(FLUSH_NON_TRANS_TABLES)). So at BACKUP_WAIT_FOR_FLUSH, maria_backup_table() copies its files as they are. Tables in the mysql schema that are not safe for online backup are still copied at BACKUP_LOCK_COMMIT: writes to the system tables (MDL_BACKUP_SYS_DML) are blocked only from that stage on, and flush_tables(FLUSH_NON_TRANS_TABLES) does not flush them. mariadb-backup also copies the non-online Aria tables under BLOCK_DDL and only the statistics and log tables under BLOCK_COMMIT. backup.backup_aria_offline: at the end of BACKUP_WAIT_FOR_FLUSH, the files of a TRANSACTIONAL=0 table and of a TRANSACTIONAL=1 PAGE_CHECKSUM=0 table are in the backup and equal to the source, and an INSERT waits for the backup lock. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41665 InnoDB assertion with result != FTS_INVALID on DELETE IGNORE with FK cascades on tables with FULLTEXT indexes Problem: ======= A foreign key cascade records its FTS operations (FTS_DELETE, FTS_INSERT) with fts_trx_add_op() while the cascade is still being processed, before it is known whether the row operation succeeds. If the row operation then fails with an error that the statement survives, row_mysql_handle_errors() rolls back the data to the row savepoint. The FTS state is not rolled back, because fts_savepoint_rollback_last_stmt() is only called when the whole statement is rolled back. The stale FTS operations stay in trx->fts_trx. When the next row cascades into the same child row, the same operation is recorded again and fts_trx_row_get_new_state() hits an invalid transition (FTS_DELETE -> FTS_DELETE), which crashes the server. Solution: ======== Make the buffered FTS changes follow the undo log numbering, like trx_t::mod_tables. fts_trx_t now only holds the tables modified by the transaction. Each fts_trx_table_t has a vector of operations. Every operation records the document id, the new row state and trx_t::undo_no at the time of fts_trx_add_op(). Operations are appended and no longer merged. trx_t::rollback_low(savept) calls the new fts_trx_rollback(), which removes from the end of each table's vector the operations whose undo_no is greater than the savepoint, and removes the tables that become empty. A row is recorded after its change, so its operations are newer than the savepoint that was taken before the row, while the operations of earlier successful rows are not. Failed rows, statement rollback and ROLLBACK TO SAVEPOINT are all handled by this one mechanism. fts_commit_table() builds the per-document row states from the operations, using the existing state transitions, and the rest of the commit is unchanged. Remove the fts_savepoint_*() functions, fts_undo_last_stmt() and the savepoint copying, together with their calls in ha_innodb.cc. SAVEPOINT no longer copies all buffered rows. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Implement copying of Aria files with reading of big blocks aria_read_index() and aria_read_data() read up to buffer_size bytes at a time, check the page checksum of every block, and re-read only the blocks with a wrong checksum. Tables without checksums are copied as they are. A simpler interface reads through a whole table: longlong aria_read_index_file(ARIA_BACKUP_CONTEXT *context, uchar *buffer, size_t buff_length); longlong aria_read_data_file(ARIA_BACKUP_CONTEXT *context, uchar *buffer, size_t buff_length); One should call both in a loop until the return is <= 0 0 means end of file, a negative value means error. storage/maria/test_ma_backup.c tests the code and can be used as an example of how to use the functions. Ported from commit 5d3388f180c33291909cbba422d9dd05049fef0a on the bb-maria-backup branch. Not ported: the my_dir.h and my_dir.c changes (they fix a function that this branch does not have), aria_open_files_for_backup() and the backup_lock() signature change (BACKUP SERVER opens the files in its own way), and the test backup.backup_aria_log. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '10.11' into bb-11.4-release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: copy Aria data files before the log BACKUP SERVER copied the Aria log at the start of BACKUP_LOCK_COMMIT and the .MAD and .MAI files after it. A transactional table can be written under BACKUP_LOCK_COMMIT, so a copied page could have an LSN after the end of the copied log, and recovery of the backup failed. A plain file copy could also read a page while the page cache wrote it. Aria now copies its table files in maria_backup_step(): BACKUP_WAIT_FOR_FLUSH: DDL is blocked. Copy the tables that are safe for online backup (TRANSACTIONAL=1 with PAGE_CHECKSUM=1) with aria_read_index_file() and aria_read_data_file(), which re-read a page with a wrong checksum. Each file is copied up to its size at the start of the copy. The log is copied later, after translog_flush() of the horizon, so it covers every page LSN in the copied files. BACKUP_LOCK_COMMIT: copy the other Aria tables as whole files, after the log, as before. Their writes are blocked in this stage. maria_backup_file() no longer accepts .MAD and .MAI files, so the generic directory scan does not copy them a second time. The backup lock that aria_open_files_for_backup() took in the bb-maria-backup branch is not needed: DDL is blocked from BACKUP_WAIT_FOR_FLUSH, and backup_step() runs in worker threads that have no THD. backup.backup_aria_rollback now passes; record its result. Create the backup in MYSQLTEST_VARDIR, so that the result does not depend on the worker number. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Analysis: The check blocked non-ROW_RESULT subselects with single field. This eventually resulted in crash in absence of fields in the virtual_tmp_table. Fix: Disallow single-field subselect whose result type is non-row result and throw error. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: BACKUP SERVER during an Aria DELETE A DELETE on a TRANSACTIONAL=1 Aria table runs while BACKUP SERVER copies the files. With a small page cache, the DELETE evicts and writes data pages whose LSN is after the end of the copied Aria log. Aria recovery of the backup then fails an assertion in get_rowpos_in_head_or_tail_page(). The test has no .result file yet: the server crashes on restart from the backup, so the expected output cannot be recorded until the Aria backup copies the log up to the newest LSN in the copied data files. Test case by Marko Mäkelä. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41767: Wrong result for row comparison of trigger NEW/OLD: NEW = OLD returns 1 after a column change, OLD = (1,2,3) returns 0 Analysis: Multi-argument row comparisons returned incorrect results because all column comparators evaluated the exact same column value. Item_trigger_row::addr(i) returned the address of a single shared member variable (m_last_item_ptr) making all columns to evaluate against the final field. Fix: Added an m_item_array member to Item_trigger_row to hold unique pointers for each field. Populated the array during populate_with_trigger_fields(). Updated addr(i) to return pointer for each column index. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '11.4' into bb-11.4-release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MDEV-36295 backport followup, wrong version marker in test file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Yuchen Pei
ycp@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25848 do not let get_mm_parts() match cloned key parts get_claimed_key_part() appended clones at param->key_parts_end, so every later get_mm_parts() call iterated over them too and cloned each clone again. N independent predicates on the same RTREE/ARRAY field thus produced 2^(N-1) key parts, exhausting MAX_KEY at the 8th predicate (e.g. 8 ORed "x MEMBER OF (js)" lost range access). Keep clones in a separate region after key_parts_end, tracked by RANGE_OPT_PARAM::key_part_clones_end. get_mm_parts() only walks key_parts..key_parts_end, so each predicate creates at most one clone and N predicates use N key parts. Assisted-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: fail if the Aria log is read-only After a log write error, the Aria log is read-only and translog_flush() returns success without writing. The log files can then end before the end of the backup log, which maria_backup_end(BACKUP_LOCK_COMMIT) sampled. The log copy could succeed while recovery of the backup stops before that end, with data pages from after it. Fail with ER_ERROR_ON_WRITE if the log is not in the TRANSLOG_OK state. The test needs a non-debug build, because translog_stop_writing() fails a debug assertion. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41585 Multi-table UPDATE with ORDER BY using a temporary table assigns values computed from the last row read When ORDER BY makes the join of a multi-table UPDATE resolve via a temporary table, the join first writes all its rows to that table and then, after sorting, reads them back and calls multi_update::send_data() for each. MDEV-14551 made the rowids of the updated tables travel through the join temp table (JOIN::add_fields_for_current_rowid() and multi_update::prepare2()), but the SET values did not: the select list of the join is empty, so send_data() evaluated them with fill_record() against the tables' record buffers, which by then hold the last row read during the join. Every updated row got the value computed from that one row, e.g. UPDATE t1, t2 SET t2.v = t2.v + 1 ORDER BY t1.id set all rows of t2 to the same value with InnoDB. With MyISAM the one-row t1 was a system table, the ORDER BY was removed and no temp table was used, which hid the problem. multi_update::initialize_tables() now adds the non-constant SET values to JOIN::all_fields as hidden fields, the same way ORDER BY items and the rowids are added, so they are computed into the join temp table while the rows they read are current. multi_update::prepare2() then replaces each value in values_for_table[] with the temp table item in the same ref_ptrs slot. The hidden fields need ref_ptrs slots. The rowids already used the slack left by item_list.elements (the SET targets, while the select list is empty), so st_select_lex::get_cardinality_of_ref_ptrs_slice() now reserves item_list.elements more for the top-level select of an UPDATE. This includes single-table UPDATE, because a prepared single-table UPDATE can allocate the ref array on its first execution and run as a multi-table UPDATE on a later one. Putting the values into the select list (total_list) instead was rejected: JOIN::prepare() would fix them before multi_update::prepare() collects the columns they read in TABLE::tmp_set, which safe_update_on_fly() relies on, and setup_fields() would push them into select_lex->pre_fix on the read-only statement arena of a later PS execution. This commit was prepared with Claude Code (Opus 5.5), which analysed the failure with rr, implemented the fix and the test, and ran the main, versioning, period, vcol, gcol, compat/oracle, compat/maxdb, json, funcs_1, funcs_2, sys_vars and innodb suites in normal and --ps-protocol modes. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41564: Make optimizer context replay warnings translatable Replace ER_JSON_OPTIMIZER_REPLAY_CONTEXT_MATCH_FAILED, which took hard-coded English fragments as arguments, with six specific messages (table, index, range context, ranges, cost_for_index_read_calls, records_in_range_calls) that have their own format strings and Spanish translations. Also fix format specifiers: print ha_rows with %llu and the parse error offset with %lld. Add tests that replay each mismatch under lc_messages=es_ES. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch 'bb-11.4-release' into bb-11.8-release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alexey Botchkov
holyfoot@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41430 auth_pam_tool leaves zombie processes. As the auth_pam_tool claims root privileges, the mariadbd can't kill it if it hangs. So instead of sending the SIGKILL we spawn the child process in the auth_pam_tool to do the work when the parent auth_pam_tool exits at once. So no zombie should appear. The auth_pam_tool now sets the alarm(120) to terminate itself if hangs. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41766: Assertion marked_for_read() failed in Field_long::val_int on row comparison of NEW/OLD in AFTER trigger Analysis: Whole-row trigger comparisons (NEW = OLD) evaluate constituent fields without registering them in the table's read bitmap. This causes a marked_for_read() assertion crash when reading field values during trigger execution. Fix: Call register_field_in_read_map() on each field to ensure proper read map marking when fixing fields. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: recover Aria from the start checkpoint BACKUP SERVER copied aria_log_control after the log, at BACKUP_LOCK_COMMIT. The Aria table files are copied earlier, at BACKUP_WAIT_FOR_FLUSH. A checkpoint between the two copies made recovery of the backup start from that checkpoint. Recovery then skipped the REDO for pages that were not dirty at that checkpoint, but the copied files had older versions of those pages. maria_backup_start(BACKUP_START): create the backup context, disable the log purge until maria_backup_end(BACKUP_FINISHED), and sample last_checkpoint_lsn. maria_backup_control_file(): write aria_log_control to the backup with the sampled checkpoint, the last copied log file and max_trid_in_control_file, instead of copying the file of the server. ma_control_file_image() builds the file contents. maria_backup_create(): create a file in the target directory or start it in the stream; used by maria_backup_copy() and maria_backup_control_file(). The test backup.backup_aria_checkpoint runs a checkpoint after the table copy (new DEBUG_SYNC point maria_backup_tables_copied). It fails with ER_NOT_KEYFILE when aria_log_control has the checkpoint of BACKUP_LOCK_COMMIT. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: torn read of an Aria page in BACKUP SERVER aria_read_index() and aria_read_data() read a page again when its checksum does not match, which happens when a concurrent write tears the read (possible on ext4, for example). No test covered this. aria_backup_debug_tear(): with the debug keyword aria_backup_torn_read, change the second half of the first checked page of each read call once; with aria_backup_torn_read_always, on every read. backup.backup_aria_torn_read: with aria_backup_torn_read, BACKUP SERVER succeeds and the restored table is correct; with aria_backup_torn_read_always, BACKUP SERVER fails with HA_ERR_WRONG_CRC after MAX_RETRY reads. With MAX_RETRY 0, the first case fails too. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||