Home - Waterfall Grid T-Grid Console Builders Recent Builds Buildslaves Changesources - JSON API - About

Console View


Categories: connectors experimental galera main
Legend:   Passed Failed Warnings Failed Again Running Exception Offline No data

connectors experimental galera main
Thirunarayanan Balathandayuthapani
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list)

Problem:
=======
fts_ast_free_node() and fts_ast_free_list() called each other, so
releasing the parse tree consumed one pair of thread stack frames
for every level of the tree.  sub_expr: '(' expr_lst ')' creates
one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean
mode query with 2000 nested parentheses builds a chain of 4002
nodes, and fts_query_free() overflowed the thread stack
while freeing it.

fts_ast_visit() does not reach that depth, because
fts_ast_visit_sub_exp() limits the sub-expression nesting to
32 levels and returns DB_OUT_OF_MEMORY.
The parser has built the whole tree by then, and  it still has
to be freed.

fts_ast_node_print_recursive() recurses the same way. It is called
from fts_query_parse() when innodb_ft_enable_diag_print is enabled,
so it overflows the stack right after parsing, before the query is
executed.


Solution:
========
fts_ast_free_node(): Free the sub-tree with an explicit stack
instead of by recursion. The stack is threaded through the
next pointer of the very nodes that are about to be freed,
so it needs no extra memory and cannot fail to allocate.
A node is only pushed once it has been detached from the tree.
The children of a list are already chained to each other by next,
so a whole list is spliced onto the stack in one step.

fts_ast_free_list(): Removed, no longer needed.

fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and
print "..." instead of descending further.
Alessandro Vetere
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
Aleksey Midenkov
MDEV-40821 Wrong result after PORTION OF with subquery (11.4)

Single-table DELETE and UPDATE converted to multi-table (when a
subquery references the target table, or with UPDATE also another
table via semi-join) skipped FOR PORTION OF row splitting and the
constant expression check, so they deleted or updated whole rows
instead of the portion.

The fix prohibits processing DELETE ... FOR PORTION OF and UPDATE ...
FOR PORTION OF as multi-table, like DELETE ... RETURNING.
Oleksandr Byelkin
Merge branch 'bb-11.8-release' into bb-12.3-release
Khaled Riyad
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.
Alessandro Vetere
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
Vladislav Vaintroub
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z

The test patches user.MAI from perl, opened in text mode. On Windows
that strips a trailing 0x1A byte on close, so the index file becomes
one byte shorter and the server reports a size mismatch instead of
repairing the table. Open the file with the :raw layer.

Assisted-by: Claude:claude-sonnet-5-5
Jan Lindström
Record test result after protocol change.
Alessandro Vetere
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
Alessandro Vetere
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
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (11.4)

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (10.11)

The test .cnf does not include default_client.cnf, so clients do not
get loose-disable-ssl-verify-server-cert. Since 11.4 the client
verifies the server certificate by default. With WITH_SSL=bundled
Connector/C is built with GnuTLS, which reports the CA-signed test
server certificate with an unknown issuer as
MARIADB_TLS_VERIFY_UNKNOWN, so check-testcase fails to connect to
server 2 with "The certificate issuer is unknown".

The fix includes default_client.cnf into the test .cnf, like other
rpl tests do.
Jan Lindström
MDEV-40727 fix test path match, log synced filesystems on all platforms

Match only the trailing test-specific path, not the full literal path.
Remove the non-Linux early return so sync_filesystems() always logs
each flushed filesystem, and verify table content after SST.

Assisted-by: Claude:claude-4.6-sonnet
Oleksandr Byelkin
Merge branch '12.3' into bb-12.3-release
Kristian Nielsen
After-merge fix of compilation failures

Signed-off-by: Kristian Nielsen <[email protected]>
sjaakola
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
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
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client

Schannel on Windows is not OpenSSL either, but handles these cases.

Assisted-by: Claude:claude-sonnet-5-5
Vladislav Vaintroub
MDEV-40878 avoid repeated parsing of PROXY headers

Do not parse multiple proxy headers. The protocol spec says the header is
at the beginning of a connection, so there could only be one.

According to example in the spec, in multi-layer scenarios, where several
proxies are involved between client and backend, the intermediate proxy
is supposed to be configured to replace the existing header. Thus multiple
headers are not expected.
Aleksey Midenkov
Merge 10.11 into 11.4
Thirunarayanan Balathandayuthapani
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit

expr_lst: expr_lst sub_expr wrapped the expression list parsed so
far in a newly created FTS_AST_LIST for every sub-expression,
so a query such as '(word)' repeated N times built N nested lists.
fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the
thread stack; the default thread_stack was exhausted at about
2300 repetitions.

Append the sub-expression to the list that is already being built,
and create a list only when there is none yet, the way
the neighbouring expr_lst: expr_lst expr rule has always done.
The sub-expressions now become siblings of a single list and
the depth no longer grows.

This also corrects '+term (subexpr)'. The FTS_EXIST pass used to
run to completion in the inner list before the sub-expression was
unioned at the outer level, so rows that matched only the
sub-expression were returned.

Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35
Khaled Riyad
MDEV-41140 mariadb-server.postinst chown dereferences symlinks

The postinst, preinst, rpm postin and mysqld_safe scripts followed
symlinks when fixing ownership and permissions under /var/log/mysql
and /var/lib/mysql. Use -h and find -execdir, drop the rpm chmod, and
let mysqld_safe write as the mysql user, so symlinks there are no
longer dereferenced.

Behavior changes.
- symlinks inside these directories are no longer followed
- only the top level of /var/log/mysql is adjusted, not subdirectories
- the rpm scriptlet no longer runs chmod on the permission database
Alessandro Vetere
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
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
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
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.
Oleksandr Byelkin
MDEV-35867 mariadb-check --repair does not repair sequences, only changes the status to OK

REPAIR of a sequence table with more or fewer than one row reported OK.
Now ha_sequence::repair() checks the row count after the engine repair
and reports the sequence as corrupt.

Also a failed table recreate in REPAIR was reported as
"Table is already up to date" (bool result taken as HA_ADMIN_ALREADY_DONE).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Monty
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
Merge branch '10.11' into bb-11.4-release
Alessandro Vetere
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
Oleksandr Byelkin
MDEV-39566 crash on a sorted scan of performance_schema.status_by_*

The bitmap of materialized rows in PFS_table_context was sized by the
live row count of the buffer container, which grows while a scan runs:
a sorted scan sizes it twice and asserted when the two sizes differed,
and set_item() could write past its end.  status_by_account used the
thread local key of status_by_host.  The allocation used the number of
bits in a word as its size in bytes.  m_last_item started at 0, so
set_item(0) did nothing and rnd_pos() dropped the first row.

Size the bitmap by the container maximum, which is fixed at startup;
give status_by_account its own key THR_PFS_SBA; allocate sizeof(ulong)
per word; start m_last_item at a sentinel.

Co-Authored-By: Claude Opus 5 <[email protected]>
Alessandro Vetere
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
Oleksandr Byelkin
Merge branch '11.4' into bb-11.4-release
Alessandro Vetere
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
Oleksandr Byelkin
Merge branch 'bb-11.4-release' into bb-11.8-release
Alexey Botchkov
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
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
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
Rex Johnston
MDEV-36295 backport followup, wrong version marker in test file
Alessandro Vetere
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