MySQL 8.4.0
Source Code Documentation
thr_lock.cc File Reference

Read and write locks for Posix threads. More...

#include "my_config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "m_string.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_inttypes.h"
#include "my_list.h"
#include "my_macros.h"
#include "my_sys.h"
#include "my_systime.h"
#include "my_thread.h"
#include "my_thread_local.h"
#include "mysql/psi/mysql_cond.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/psi/mysql_table.h"
#include "mysql/psi/mysql_thread.h"
#include "mysql/psi/psi_stage.h"
#include "mysql/psi/psi_table.h"
#include "mysys/mysys_priv.h"
#include "template_utils.h"
#include "thr_lock.h"
#include "thr_mutex.h"

Macros

#define MAX_THREADS   100
 
#define MAX_LOCKS   100
 
#define check_locks(A, B, C)
 
#define LOCK_CMP(A, B)
 

Functions

void thr_set_lock_wait_callback (void(*before_wait)(void), void(*after_wait)(void))
 
static bool thr_lock_owner_equal (THR_LOCK_INFO *rhs, THR_LOCK_INFO *lhs)
 
void thr_lock_init (THR_LOCK *lock)
 
void thr_lock_delete (THR_LOCK *lock)
 
void thr_lock_info_init (THR_LOCK_INFO *info, my_thread_id thread_id, mysql_cond_t *suspend)
 
void thr_lock_data_init (THR_LOCK *lock, THR_LOCK_DATA *data, void *param)
 
static bool has_old_lock (THR_LOCK_DATA *data, THR_LOCK_INFO *owner)
 
static void wake_up_waiters (THR_LOCK *lock)
 Wake up all threads which pending requests for the lock can be satisfied. More...
 
static enum enum_thr_lock_result wait_for_lock (struct st_lock_list *wait, THR_LOCK_DATA *data, THR_LOCK_INFO *owner, bool in_wait_list, ulong lock_wait_timeout)
 
enum enum_thr_lock_result thr_lock (THR_LOCK_DATA *data, THR_LOCK_INFO *owner, enum thr_lock_type lock_type, ulong lock_wait_timeout)
 
static void free_all_read_locks (THR_LOCK *lock, bool using_concurrent_insert)
 
void thr_unlock (THR_LOCK_DATA *data)
 
static void sort_locks (THR_LOCK_DATA **data, uint count)
 
enum enum_thr_lock_result thr_multi_lock (THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
 
void thr_lock_merge_status (THR_LOCK_DATA **data, uint count)
 Ensure that all locks for a given table have the same status_param. More...
 
void thr_multi_unlock (THR_LOCK_DATA **data, uint count)
 
void thr_abort_locks_for_thread (THR_LOCK *lock, my_thread_id thread_id)
 
static void thr_print_lock (const char *name, struct st_lock_list *list)
 
void thr_print_locks (void)
 

Variables

ulong locks_immediate = 0L
 
ulong locks_waited = 0L
 
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE
 
LISTthr_lock_thread_list
 
ulong max_write_lock_count = ~(ulong)0L
 
static void(* before_lock_wait )(void) = nullptr
 
static void(* after_lock_wait )(void) = nullptr
 

Detailed Description

Read and write locks for Posix threads.

Every thread must acquire all locks it needs through thr_multi_lock() to avoid dead-locks. A lock consists of a master lock (THR_LOCK), and lock instances (THR_LOCK_DATA). Any thread can have any number of lock instances (read and write:s) on any lock. All lock instances must be freed. Locks are prioritized according to:

The current lock types are:

TL_READ # Low priority read TL_READ_WITH_SHARED_LOCKS TL_READ_HIGH_PRIORITY # High priority read TL_READ_NO_INSERT # Read without concurrent inserts TL_WRITE_ALLOW_WRITE # Write lock that allows other writers TL_WRITE_CONCURRENT_INSERT

Insert that can be mixed when selects

Allows lower locks to take over

TL_WRITE_LOW_PRIORITY # Low priority write TL_WRITE # High priority write TL_WRITE_ONLY # High priority write

Abort all new lock request with an error

Locks are prioritized according to:

WRITE_ALLOW_WRITE, WRITE_CONCURRENT_INSERT, WRITE_LOW_PRIORITY, READ, WRITE, READ_HIGH_PRIORITY and WRITE_ONLY

Locks in the same privilege level are scheduled in first-in-first-out order.

To allow concurrent read/writes locks, with 'WRITE_CONCURRENT_INSERT' one should put a pointer to the following functions in the lock structure: (If the pointer is zero (default), the function is not called)

check_status: Before giving a lock of type TL_WRITE_CONCURRENT_INSERT, we check if this function exists and returns 0. If not, then the lock is upgraded to TL_WRITE_LOCK In MyISAM this is a simple check if the insert can be done at the end of the datafile. update_status: Before a write lock is released, this function is called. In MyISAM this functions updates the count and length of the datafile get_status: When one gets a lock this functions is called. In MyISAM this stores the number of rows and size of the datafile for concurrent reads.

The lock algorithm allows one to have one TL_WRITE_CONCURRENT_INSERT lock at the same time as multiple read locks.

Macro Definition Documentation

◆ check_locks

#define check_locks (   A,
  B,
 
)

◆ LOCK_CMP

#define LOCK_CMP (   A,
 
)
Value:
((uchar *)(A->lock) - (uint)((A)->type) < \
(uchar *)(B->lock) - (uint)((B)->type))
unsigned char uchar
Definition: my_inttypes.h:52
required string type
Definition: replication_group_member_actions.proto:34

◆ MAX_LOCKS

#define MAX_LOCKS   100

◆ MAX_THREADS

#define MAX_THREADS   100

Function Documentation

◆ free_all_read_locks()

static void free_all_read_locks ( THR_LOCK lock,
bool  using_concurrent_insert 
)
inlinestatic

◆ has_old_lock()

static bool has_old_lock ( THR_LOCK_DATA data,
THR_LOCK_INFO owner 
)
inlinestatic

◆ sort_locks()

static void sort_locks ( THR_LOCK_DATA **  data,
uint  count 
)
static

◆ thr_abort_locks_for_thread()

void thr_abort_locks_for_thread ( THR_LOCK lock,
my_thread_id  thread_id 
)

◆ thr_lock()

enum enum_thr_lock_result thr_lock ( THR_LOCK_DATA data,
THR_LOCK_INFO owner,
enum thr_lock_type  lock_type,
ulong  lock_wait_timeout 
)

◆ thr_lock_data_init()

void thr_lock_data_init ( THR_LOCK lock,
THR_LOCK_DATA data,
void *  param 
)

◆ thr_lock_delete()

void thr_lock_delete ( THR_LOCK lock)

◆ thr_lock_info_init()

void thr_lock_info_init ( THR_LOCK_INFO info,
my_thread_id  thread_id,
mysql_cond_t suspend 
)

◆ thr_lock_init()

void thr_lock_init ( THR_LOCK lock)

◆ thr_lock_merge_status()

void thr_lock_merge_status ( THR_LOCK_DATA **  data,
uint  count 
)

Ensure that all locks for a given table have the same status_param.

This is a MyISAM and possibly Maria specific crutch. MyISAM engine stores data file length, record count and other table properties in status_param member of handler. When a table is locked, connection-local copy is made from a global copy (myisam_share) by mi_get_status(). When a table is unlocked, the changed status is transferred back to the global share by mi_update_status().

One thing MyISAM doesn't do is to ensure that when the same table is opened twice in a connection all instances share the same status_param. This is necessary, however: for one, to keep all instances of a connection "on the same page" with regard to the current state of the table. For other, unless this is done, myisam_share will always get updated from the last unlocked instance (in mi_update_status()), and when this instance was not the one that was used to update data, records may be lost.

For each table, this function looks up the last lock_data in the list of acquired locks, and makes sure that all other instances share status_param with it.

◆ thr_lock_owner_equal()

static bool thr_lock_owner_equal ( THR_LOCK_INFO rhs,
THR_LOCK_INFO lhs 
)
inlinestatic

◆ thr_multi_lock()

enum enum_thr_lock_result thr_multi_lock ( THR_LOCK_DATA **  data,
uint  count,
THR_LOCK_INFO owner,
ulong  lock_wait_timeout 
)

◆ thr_multi_unlock()

void thr_multi_unlock ( THR_LOCK_DATA **  data,
uint  count 
)

◆ thr_print_lock()

static void thr_print_lock ( const char *  name,
struct st_lock_list list 
)
static

◆ thr_print_locks()

void thr_print_locks ( void  )

◆ thr_set_lock_wait_callback()

void thr_set_lock_wait_callback ( void(*)(void)  before_wait,
void(*)(void)  after_wait 
)

◆ thr_unlock()

void thr_unlock ( THR_LOCK_DATA data)

◆ wait_for_lock()

static enum enum_thr_lock_result wait_for_lock ( struct st_lock_list wait,
THR_LOCK_DATA data,
THR_LOCK_INFO owner,
bool  in_wait_list,
ulong  lock_wait_timeout 
)
static

◆ wake_up_waiters()

static void wake_up_waiters ( THR_LOCK lock)
static

Wake up all threads which pending requests for the lock can be satisfied.

Parameters
lockLock for which threads should be woken up

Variable Documentation

◆ after_lock_wait

void(* after_lock_wait) (void) ( void  ) = nullptr
static

◆ before_lock_wait

void(* before_lock_wait) (void) ( void  ) = nullptr
static

◆ locks_immediate

ulong locks_immediate = 0L

◆ locks_waited

ulong locks_waited = 0L

◆ max_write_lock_count

ulong max_write_lock_count = ~(ulong)0L

◆ thr_lock_thread_list

LIST* thr_lock_thread_list

◆ thr_upgraded_concurrent_insert_lock

enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE