276 Commits

Author SHA1 Message Date
18985d8471 MDEV-19749 - MDL scalability regression after backup locks
Statements that intend to modify data have to acquire protection
against ongoing backup. Prior to backup locks, protection against
FTWRL was acquired in form of 2 shared metadata locks of GLOBAL
(global read lock) and COMMIT namespaces. These two namespaces
were separate entities, they didn't share data structures and
locking primitives. And thus they were separate contention
points.

With backup locks, introduced by 7a9dfdd, these namespaces were
combined into a single BACKUP namespace. It became a single
contention point, which doubled load on BACKUP namespace data
structures and locking primitives compared to GLOBAL and COMMIT
namespaces. In other words system throughput has halved.

MDL fast lanes solve this problem by allowing multiple contention
points for single MDL_lock. Fast lane is scalable multi-instance
registry for leightweight locks. Internally it is just a list of
granted tickets, close counter and a mutex.

Number of fast lanes (or contention points) is defined by the
metadata_locks_instances system variable. Value of 1 disables fast
lanes and lock requests are served by conventional MDL_lock data
structures.

Since fast lanes allow arbitrary number of contention points, they
outperform pre-backup locks GLOBAL and COMMIT.

Fast lanes are enabled only for BACKUP namespace. Support for other
namespaces is to be implemented separately.

Lock types are divided in 2 categories: lightweight and heavyweight.

Lightweight lock types represent DML: MDL_BACKUP_DML,
MDL_BACKUP_TRANS_DML, MDL_BACKUP_SYS_DML, MDL_BACKUP_DDL,
MDL_BACKUP_ALTER_COPY, MDL_BACKUP_COMMIT. They are fully compatible
with each other. Normally served by corresponding fast lane, which is
determined by thread_id % metadata_locks_instances.

Heavyweight lock types represent ongoing backup: MDL_BACKUP_START,
MDL_BACKUP_FLUSH, MDL_BACKUP_WAIT_FLUSH, MDL_BACKUP_WAIT_DDL,
MDL_BACKUP_WAIT_COMMIT, MDL_BACKUP_FTWRL1, MDL_BACKUP_FTWRL2,
MDL_BACKUP_BLOCK_DDL. These locks are always served by conventional
MDL_lock data structures. Whenever such lock is requested, fast
lanes are closed and all tickets registered in fast lanes are
moved to conventional MDL_lock data structures. Until such locks
are released or aborted, lightweight lock requests are served by
conventional MDL_lock data structures.

Strictly speaking moving tickets from fast lanes to conventional
MDL_lock data structures is not required. But it allows to reduce
complexity and keep intact methods like: MDL_lock::visit_subgraph(),
MDL_lock::notify_conflicting_locks(), MDL_lock::reschedule_waiters(),
MDL_lock::can_grant_lock().

It is not even required to register tickets in fast lanes. They
can be implemented basing on an atomic variable that holds two
counters: granted lightweight locks and granted/waiting heavyweight
locks. Similarly to MySQL solution, which roughly speaking has
"single atomic fast lane". However it appears to be it won't bring
any better performance, while code complexity is going to be much
higher.
2025-07-15 23:19:06 +04:00
5b32446217 MDL_lock encapsulation: removed redundant methods
Given that MDL_lock::m_strategy is only accessed by MDL_lock methods,
there is no point in having MDL_lock::needs_notification() and
MDL_lock::hog_lock_types_bitmap() getters anymore.

MDL_lock::has_pending_conflicting_lock() moved to MDL_lock class.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
3ca5e08f0e MDL_lock encapsulation: final
All MDL_lock objects and types are private now. Along with a set
of methods which are not used outside.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
02eb8f7246 MDL_lock encapsulation: MDL_lock::get_key()
Avoid accessing MDL_lock::key from outside of MDL_lock class directly,
use MDL_lock::get_key() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
36bec5697b MDL_lock encapsulation: try_acquire_lock_impl()
Avoid accessing MDL_lock members from MDL_context::acquire_lock()
MDL_context::try_acquire_lock_impl() and MDL_map::find_or_insert().
This is done by implementing MDL_map::try_acquire_lock() and
MDL_lock::try_acquire_lock(). With this patch MDL_lock members are
not accessed outside of the class.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
9d34cee80b Move m_wait.reset_status() out of critical section
MDL_wait::m_wait_status has to be reset to EMPTY state before going
into waiting routines. There're three options to get it done:

1. Before MDL_lock::rw_lock critical section of
   MDL_context::acquire_lock(). In this case MDL_context is not exposed
   neither via MDL_lock::m_waiting nor has it MDL_context::m_waiting_for
   set.
   Cons: m_wait.reset_status() brings unwanted overhead when lock can
   be served immediately.

2. Current solution. Within MDL_lock::rw_lock critical section of
   MDL_context::acquire_lock(). MDL_context::m_waiting_for is not yet set
   however MDL_context was already exposed via MDL_lock::m_waiting list.
   The latter is not a problem since we're still holding exclusive lock
   on MDL_lock::rw_lock.
   Cons: increases critical section size for no good reason.

3. Whenever MDL_wait is created and after wait in
   MDL_context::acquire_lock() is completed. At this point MDL_context
   is not exposed via MDL_lock::m_waiting anymore and
   MDL_context::m_waiting_for is reset.
   Cons: none, it is just plain beauty.

Now MDL_wait::m_wait_status is manipulated as following:

EMPTY - set whenever MDL_wait object is created and after each wait
GRANTED - can be set by a thread that releases incompatible lock
VICTIM - can be set either by owner thread or by concurrent higher
         priority thread during deadlock detection
TIMEOUT - always set by owner thread
KILLED - always set by owner thread

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
329bff638b MDL_lock encapsulation: try_acquire_lock()
Avoid accessing MDL_lock::m_rwlock from MDL_context::try_acquire_lock()
and MDL_context::acquire_lock(), code moved to
MDL_context::try_acquire_lock_impl() instead. It is an intermediate
change that reduce uses of MDL_lock::m_rwlock out of MDL_lock class.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
a955e9dd61 MDL_ticket cleanup
Removed useless MDL_ticket::create() and MDL_ticket::destroy()
indirection. It didn't serve any purpose.

Moved mysql_mdl_create() PFS call out of critical section.

Moved ticket->m_time assignment out of MDL_lock::m_rwlock protection.
It increases critical section size for no good reason. Assigning it
before critical section must be good enough for statistics purposes,
since we must not do long waits here anyway.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
2a3b999a56 MDL_lock encapsulation: MDL_lock::remove_ticket()
Avoid accessing MDL_lock::m_waiting from MDL_context::acquire_lock(),
use MDL_lock::abort_wait() instead.

Avoid accessing MDL_lock::m_granted from MDL_context::release_lock(),
use MDL_lock::release() instead.

Avoid accessing MDL_lock::m_strategy and MDL_lock::m_rwlock from
MDL_map::remove(), code moved to MDL_lock::remove_ticket() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
5aa4ccf4c4 MDL_lock encapsulation: notify_conflicting_locks()
Avoid accessing MDL_lock::m_rwlock from MDL_context::acquire_lock(),
use MDL_lock::notify_conflicting_locks_if_needed() instead.

Also MDL_lock::needs_notification() doesn't require MDL_lock::m_rwlock
protection, so it is moved out of critical section.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
0c31f85a67 MDL_lock encapsulation: MDL_lock::upgrade()
Avoid accessing MDL_lock::m_granted and MDL_lock::m_rwlock from
MDL_ticket::upgrade_shared_lock(), use MDL_lock::upgrade() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
255a22c3a0 MDL_lock encapsulation: MDL_lock::downgrade()
Avoid accessing MDL_lock::m_granted and MDL_lock::m_rwlock from
MDL_ticket::downgrade_lock(), use MDL_lock::downgrade() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
ecd47cfa5c MDL_lock encapsulation: add_cloned_ticket()
Avoid accessing MDL_lock::m_granted and MDL_lock::m_rwlock from
MDL_context::clone_ticket(), use MDL_lock::add_cloned_ticket() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
fba71705df MDL_lock encapsulation: MDL_lock::iterate()
Avoid accessing MDL_lock::m_waiting, MDL_lock::m_granted and
MDL_lock::m_rwlock from mdl_iterate_lock(), use MDL_lock::iterate()
instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
c2881f04e8 MDL_lock encapsulation: MDL_lock::get_lock_owner()
Avoid accessing MDL_lock::m_rwlock from MDL_map::get_lock_owner(),
code moved to MDL_lock::get_lock_owner() instead.

get_lock_owner() doesn't have to check BACKUP namespace since it is
used by user level locks only.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
2025-07-15 23:19:06 +04:00
717c12de0e Fix typos in C comments inside sql/ 2025-03-14 12:08:56 +04:00
33907f9ec6 Merge 11.4 into 11.7 2024-12-02 17:51:17 +02:00
3d23adb766 Merge 10.6 into 10.11 2024-11-29 13:43:17 +02:00
7d4077cc11 Merge 10.5 into 10.6 2024-11-29 12:37:46 +02:00
840fe316d4 MDEV-34348: my_hash_get_key fixes
Partial commit of the greater MDEV-34348 scope.
MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict

Change the type of my_hash_get_key to:
 1) Return const
 2) Change the context parameter to be const void*

Also fix casting in hash adjacent areas.

Reviewed By:
============
Marko Mäkelä <marko.makela@mariadb.com>
2024-11-23 08:14:22 -07:00
db5d1cde45 MDEV-34857: Implement --slave-abort-blocking-timeout
If a slave replicating an event has waited for more than
@@slave_abort_blocking_timeout for a conflicting metadata lock held by a
non-replication thread, the blocking query is killed to allow replication to
proceed and not be blocked indefinitely by a user query.

Reviewed-by: Monty <monty@mariadb.org>
Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
2024-09-04 11:44:14 +02:00
c91ec6a5c1 Added Lock_time_ms and Table_catalog columns to metadata_lock_info
If compiled for debugging, LOCK_DURATION is also filled in.
2024-07-03 13:20:33 +03:00
27a3366663 Merge 10.6 into 10.11 2024-06-27 10:26:09 +03:00
0076eb3d4e Merge 10.5 into 10.6 2024-06-24 13:09:47 +03:00
db0c28eff8 MDEV-33746 Supply missing override markings
Find and fix missing virtual override markings.  Updates cmake
maintainer flags to include -Wsuggest-override and
-Winconsistent-missing-override.
2024-06-20 11:32:13 -04:00
b81d717387 Merge 10.6 into 10.11 2024-06-11 12:50:10 +03:00
27834ebc91 Merge 10.5 into 10.6 2024-06-10 15:22:15 +03:00
a2bd936c52 MDEV-33161 Function pointer signature mismatch in LF_HASH
In cmake -DWITH_UBSAN=ON builds with clang but not with GCC,
-fsanitize=undefined will flag several runtime errors on
function pointer mismatch related to the lock-free hash table LF_HASH.

Let us use matching function signatures and remove function pointer
casts in order to avoid potential bugs due to undefined behaviour.

These errors could be caught at compilation time by
-Wcast-function-type-strict, which is available starting with clang-16,
but not available in any version of GCC as of now. The old GCC flag
-Wcast-function-type is enabled as part of -Wextra, but it specifically
does not catch these errors.

Reviewed by: Vladislav Vaintroub
2024-06-10 12:35:33 +03:00
bf0aa99aeb MDEV-34237: On Startup: UBSAN: runtime error: call to function MDL_lock::lf_hash_initializer lf_hash_insert through pointer to incorrect function type 'void (*)(st_lf_hash *, void *, const void *)'
A few different incorrect function type UBSAN issues have been
grouped into this patch.

The only real potentially undefined behavior is an error about
show_func_mutex_instances_lost, which when invoked in
sql_show.cc::show_status_array(), puts 5 arguments onto the stack;
however, the implementing function only actually has 3 parameters (so
only 3 would be popped). This was fixed by adding in the remaining
parameters to satisfy the type mysql_show_var_func.

The rest of the findings are pointer type mismatches that wouldn't
lead to actual undefined behavior. The lf_hash_initializer function
type definition is

typedef void (*lf_hash_initializer)(LF_HASH *hash, void *dst, const void *src);

but the MDL_lock and table cache's implementations of this function
do not have that signature. The MDL_lock has specific MDL object
parameters:

static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)),
                                MDL_lock *lock, MDL_key *key_arg)

and the table cache has specific TDC parameters:

static void tdc_hash_initializer(LF_HASH *,
                                 TDC_element *element, LEX_STRING *key)

leading to UBSAN runtime errors when invoking these functions.

This patch fixes these type mis-matches by changing the
implementing functions to use void * and const void * for their
respective parameters, and later casting them to their expected
type in the function body.

Note too the functions tdc_hash_key and tc_purge_callback had
a similar problem to tdc_hash_initializer and was fixed
similarly.

Reviewed By:
============
Sergei Golubchik <serg@mariadb.com>
2024-06-08 19:59:59 -06:00
64cce8d5bf Merge 10.6 into 10.11 2024-02-14 16:12:53 +02:00
691f923906 Merge 10.5 into 10.6 2024-02-13 20:42:59 +02:00
8ec12e0d6d Merge 10.4 into 10.5 2024-02-12 11:38:13 +02:00
ddb27a29b1 MDEV-33172 : Galera test case galera_mdl_race unstable
Add wait_condition between debug sync SIGNAL points and other
expected state conditions and refactor actual sync point for
easier to use in test case.

Signed-off-by: Julius Goryavsky <julius.goryavsky@mariadb.com>
2024-01-30 00:27:37 +01:00
04d9a46c41 Merge branch '10.6' into 10.10 2023-11-08 16:23:30 +01:00
b83c379420 Merge branch '10.5' into 10.6 2023-11-08 15:57:05 +01:00
6cfd2ba397 Merge branch '10.4' into 10.5 2023-11-08 12:59:00 +01:00
f293b2b211 cleanup 2023-10-17 14:32:05 +02:00
dbab3e8d90 Merge 10.6 into 10.8 2023-02-10 13:43:53 +02:00
6aec87544c Merge 10.5 into 10.6 2023-02-10 13:03:01 +02:00
c41c79650a Merge 10.4 into 10.5 2023-02-10 12:02:11 +02:00
08c852026d Apply clang-tidy to remove empty constructors / destructors
This patch is the result of running
run-clang-tidy -fix -header-filter=.* -checks='-*,modernize-use-equals-default' .

Code style changes have been done on top. The result of this change
leads to the following improvements:

1. Binary size reduction.
* For a -DBUILD_CONFIG=mysql_release build, the binary size is reduced by
  ~400kb.
* A raw -DCMAKE_BUILD_TYPE=Release reduces the binary size by ~1.4kb.

2. Compiler can better understand the intent of the code, thus it leads
   to more optimization possibilities. Additionally it enabled detecting
   unused variables that had an empty default constructor but not marked
   so explicitly.

   Particular change required following this patch in sql/opt_range.cc

   result_keys, an unused template class Bitmap now correctly issues
   unused variable warnings.

   Setting Bitmap template class constructor to default allows the compiler
   to identify that there are no side-effects when instantiating the class.
   Previously the compiler could not issue the warning as it assumed Bitmap
   class (being a template) would not be performing a NO-OP for its default
   constructor. This prevented the "unused variable warning".
2023-02-09 16:09:08 +02:00
26d8485244 Merge branch '10.7' into 10.8 2023-01-18 16:37:40 +01:00
d1a4f6e627 Merge 10.6 into 10.7 2023-01-17 11:41:29 +02:00
95de5248c7 MDEV-26391 BF abortable mariabackup execution
This commit changes backup execution (namely the block ddl phase),
so that node is not paused from cluster. Instead, the following
backup execution is declared as vulnerable for possible cluster
level conflicts, especially with DDL statement applying.
With this, the mariabackup execution may be aborted, if DDL
statements happen during backup execution. This abortable
backup execution is optional feature and may be
enabled/disabled by wsrep_mode: BF_ABORT_MARIABACKUP.
Note that old style node desync and pause, despite of
WSREP_MODE_BF_MARIABACKUP is needed if node is operating as
SST donor.

Reviewed-by: Jan Lindström <jan.lindstrom@mariadb.com>
2023-01-17 10:03:05 +02:00
2f70784c2a Merge branch '10.7' into 10.8 2022-10-04 11:42:37 +02:00
b6ebadaa66 Merge branch '10.6' into 10.7 2022-10-04 07:41:35 +02:00
829e8111c7 Merge 10.5 into 10.6 2022-09-26 14:34:43 +03:00
6286a05d80 Merge 10.4 into 10.5 2022-09-26 13:34:38 +03:00
3c92050d1c Fix build without either ENABLED_DEBUG_SYNC or DBUG_OFF
There are separate flags DBUG_OFF for disabling the DBUG facility
and ENABLED_DEBUG_SYNC for enabling the DEBUG_SYNC facility.
Let us allow debug builds without DEBUG_SYNC.

Note: For CMAKE_BUILD_TYPE=Debug, CMakeLists.txt will continue to
define ENABLED_DEBUG_SYNC.
2022-09-23 17:37:52 +03:00
a69cf6f07e MDEV-29613 Improve WITH_DBUG_TRACE=OFF
In commit 28325b0863
a compile-time option was introduced to disable the macros
DBUG_ENTER and DBUG_RETURN or DBUG_VOID_RETURN.

The parameter name WITH_DBUG_TRACE would hint that it also
covers DBUG_PRINT statements. Let us do that: WITH_DBUG_TRACE=OFF
shall disable DBUG_PRINT() as well.

A few InnoDB recovery tests used to check that some output from
DBUG_PRINT("ib_log", ...) is present. We can live without those checks.

Reviewed by: Vladislav Vaintroub
2022-09-23 13:40:42 +03:00