mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Sequence access conflicts with streaming replication could cause the server to hang, as shown in MDEV-38869. A sequence table is written from SEQUENCE::next_value() while SEQUENCE::mutex is held. For a streaming transaction the row write in handler::ha_write_row() would then replicate a fragment and block waiting for certification and commit order, while an applier may be waiting for the same mutex in SEQUENCE::set_value(). Neither side can proceed, the node deadlocks and the BF abort of the local transaction can never be delivered. This commit avoids the deadlock by skipping the streaming replication step for sequence table rows. The row is already in the write set and is replicated with the following fragment, or at commit. Only that one step is skipped. The skip is passed down as a parameter to wsrep_after_row() and wsrep_after_row_internal() rather than by not calling them at all, so the row is still counted against wsrep_max_ws_rows and wsrep_check_pk() still runs. A transaction using sequences heavily therefore cannot silently exceed the configured write set row limit. The commit has also a new mtr test for three sequence/SR conflict scenarios: galera.galera_sequences_bf_kill_sr - a streaming transaction and an applier competing for SEQUENCE::mutex, where both are expected to commit - the same, but with the applier also BF aborting the local transaction over a gap lock. A streaming transaction cannot be replayed, so it is rolled back and the client gets ER_LOCK_DEADLOCK. The applier is held at the abort_trx_end sync point until the abort has been issued, so that the local transaction cannot finish its fragment first - twelve row inserts on both nodes with wsrep_trx_fragment_unit=rows, so that each node reserves several sequence cache ranges and the sequence table writes land inside fragments carrying several rows. The values the two nodes hand out must not overlap
269 KiB
269 KiB