In practice WSREP_CONN_FAIL provider error code came to mean inability
to replicate writesets, and this applies not only to a situation where
the node is not connected to a primary component, but also when it is
not sufficiently synced - e.g. is receiving an SST or lags behind too
much. Change the error message from "not connected" to "not synced" to
cover all such situations.
The server state mutex must always be acquired before the client state
mutex. server_state::convert_streaming_client_to_applier() holds the
server state mutex over high_priority_service::adopt_transaction(),
after_apply(), store_globals() and
server_service::release_high_priority_service(), all of which take the
client state mutex of the applier client.
server_state::close_orphaned_sr_transactions() does the same.
transaction::commit_or_rollback_by_xid(), reached by XA COMMIT or
XA ROLLBACK of an xid owned by a streaming applier, took the two in the
opposite order: it locked the client state and then called
server_state::find_streaming_applier(), which locks the server state.
A client terminating a prepared XA transaction by xid could therefore
wait for the server state mutex while holding its own client state
mutex, deadlocking against a thread which is converting a streaming
client into a streaming applier.
Do the find_streaming_applier() lookup before locking the client state.
Nothing between the old lock point and the lookup needs the client
state mutex.
Add sync point wsrep_commit_or_rollback_by_xid_client_locked so that
the mutex order can be exercised from a test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The .gitmodules file uses the old Codership Github repo link. This
redirects to the mariadb-corporation repo, so it isn't a functional
problem, but it should still be updated to the correct repo.
Issue:
When an applier commit fails (e.g. commit order could not be
entered because the node is leaving the primary component), the caller
skipped after_apply() and left the transaction active. It is then carried
to client_state::close(), which runs the local-only after_statement() and
asserts client_state_.mode() == m_local in debug builds.
Solution:
On commit failure roll the applier transaction back and always
call after_apply() so it is terminated on the error path, mirroring the
apply-error branch.
log_dummy_write_set() is what releases commit order through
commit_order_leave() - which hands the apply error to the provider to
drive the inconsistency vote - and advances the storage engine
checkpoint. Skipping it on a rollback error leaves the seqno stuck in
commit order so all following appliers block on commit_order_enter, and
the node silently locks the cluster while staying in the primary
component.
Always call log_dummy_write_set() on the apply-error path, regardless of
the rollback result. The rollback result is still folded into ret so it
is not lost.
Although XA commit/rollback by XID does not have active transaction
with changes and does not become BF aborted by lock conflict, there
are other reasons why it can become BF aborted (e.g. session becoming
killed).
Add handling of `s_must_abort` in `commit_or_rollback_by_xid()` and
unit tests for testing correct behavior.
The provider::certify() call may be synchronous and blocking.
Unlock the mutex for the duration of provider::certify() call
to avoid deadlock if an applier tries to access the local transaction
which is executing provider::certify() call.
think SST/IST failed, at next restart will request a full SST
This patch fixes an unwanted behavior of a Galera cluster node when
Server startup fails because of an error in configuration file: after
the failure full SST is requested at the next Server startup even
though full SST is not needed (MDEV-31517).
If Server startup fails because of a configuration error, this patch
ensures that Galera state of the failing node remains unchanged. This
avoids full SST at the next Server restart.
This fix consists of three patches for the following components:
1) Server,
2) WSREP library,
3) Galera.
Passing a callback allows constructing the options string using
config service after loading the provider but before initializing
the provider. This way it is possible get options which are given
at DBMS startup, in command line or config file.
instance before the SYNCED event is delivered. Thus wsrep-lib is already
in s_disconnecting state but still will transition to s_synced albeit
with a warning. This is pointless and possibly harmful.
If we are disconnecting ignore any remaining state events from the
replication queue.
Refs codership/wsrep-lib#251
Set policy_max version to 4.0 to avoid error
Compatibility with CMake < 3.5 has been removed from CMake.
Add github workflow to check CMake compatibility for commonly used
versions and the newest ones.
An id is considered an alphanumeric string if it contains a
non-empty sequence of alphanumeric characters followed by
one or more null characters.
Fixed unit tests accordingly.
- Add a set_provider_factory() method to server_state to allow
injecting provider factory which will be called when the
provider is loaded.
Other related changes:
- Implement to_string() helper method for id class.
- Fix id ostream operator human readable id printing.
- Pass victim client_service as an argument to provider::bf_abort()
to allow passing victim context to custom provider.
- Implement prev() helper method for seqno class.
- Make server_state recover_streaming_appliers_if_not_recovered()
public. In some recovery scenarios the method must be called outside
of server_state internal code paths.
- Add storage_service requires_globals() method. The storage service
implementation may override this to return false if changing to
storage service context does not require store/reset globals.
- Change view final() to also require that the view status is not
primary for the view to be final. Also change the method name to
is_final() to avoid confusion with C++ final identifier.
- Fixes to server state handling in disconnecting and disconnected
states.
- Keep TOI meta data over whole TOI critical section.
Co-authored-by: Denis Protivensky <denis.protivensky@galeracluster.com>
Client state methods before_prepare() and before_commit() accept
a callback which is called by the provider after it can guarantee
sequential consistency. This allows application threads which wish to
maintain sequential consistency to enter before_prepare() and
before_commit() calls concurrently without waiting the prior call
to finish.
Handle the case where client_service::remove_fragments() fails,
for reasons other than bf abort. In this case, we want to make
sure that the transaction state is moved to s_must_abort, so
that we satisfy the sanity check at the end of before_prepare():
```
assert(state() == s_preparing ||
(is_xa() && state() == s_replaying) ||
(ret && (state() == s_must_abort ||
state() == s_must_replay ||
state() == s_cert_failed ||
state() == s_aborted)));
```
The gcc-11 disappeared from ubuntu-2004. Change gcc-11 os to ubuntu
22.04 where it is available.
Add gcc-13 and gcc-14 which are now available on ubuntu-2404.
In `transaction::abort_or_interrupt()` handle the case were a statement
is interrupted while transaction is in prepared state. In which case,
the transaction must remain in prepared state, until it is
committed (or rolled back).
Also in this patch: remove check for reduntant `s_must_abort` state.
MySQL defines a macro log_msg in one of its headers, which
causes log_msg to be replaced with different symbol in
some compilation units.
Fix by renaming the struct to log_msg_t to avoid the conflict.
The thread local ti_thread object was not initialized for main thread,
which caused ASAN to complain about wild pointer.
Fixed by assigning a thread local ti_thread object for main
thread too.
Avoid streaming context cleanup in after_rollback() hook, if
transaction is going to replay. Otherwise, streaming client is not
stopped and is left in streaming client map, potentially causing
"Failed to insert streaming client" warning if the transaction
goes for retry.
Remove bf abort handling `client_state::after_statement()`, since the
same logic already appears later in `transaction::after_statement()`.
Also, introduce `transaction::after_statement()` overload which takes
a lock.
In case if SR transaction gets BF aborted before it is
certified, the replay will happen but if the replay fails
due to certification conflict, the transaction is not terminated
in provider replay and will keep its streaming status.
Removed the wrong assertion about streaming status from
transaction::cleanup().
Allocate separate client state in mock_client_service::replay()
for replaying step.
Added two new test cases for streaming replication replay after
BF abort.
* Move resetting is_bf_immutable_ into trasaction::cleanup()
to ensure that it is reset to false regardless how the
transaction terminates.
* Removed redundant lock()/unlock() methods from
mock_client_state.
The transaction state is set to s_ordered_commit in
ordered_commit(). However, this is too late for making the
transaction immune for BF aborts after commit order has
been established, which happens in before_commit().
Moving the state change into before_commit() would be the
right thing to do, but that would require too many fixes
to existing applications which are using the lib.
In order to make the transaction immune for BF abort
after it has been ordered to commit, introduce additional
boolean flag which is set to true at the end of before_commit()
and is taken into account in bf_abort().
Make is_rollbacker_active() public so that the BF thread can
check if the rollbacker was started or not.
Also don't unlock the lock for launching the background
rollbacker to avoid race conditions in accessing the
victim state.
Replace ubuntu-18.04 virtual environment with ubuntu-20.04.
Compilation tests for GCC < 7 cannot be done anymore
since ubuntu-20.04 environment does not provide such an
old compilers.