![]() |
MySQL 9.1.0
Source Code Documentation
|
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 |
LIST * | thr_lock_thread_list |
ulong | max_write_lock_count = ~(ulong)0L |
static void(* | before_lock_wait )(void) = nullptr |
static void(* | after_lock_wait )(void) = nullptr |
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
TL_WRITE_LOW_PRIORITY # Low priority write TL_WRITE # High priority write TL_WRITE_ONLY # High priority write
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.
#define check_locks | ( | A, | |
B, | |||
C | |||
) |
#define LOCK_CMP | ( | A, | |
B | |||
) |
#define MAX_LOCKS 100 |
#define MAX_THREADS 100 |
|
inlinestatic |
|
inlinestatic |
|
static |
void thr_abort_locks_for_thread | ( | THR_LOCK * | lock, |
my_thread_id | thread_id | ||
) |
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 | ||
) |
void thr_lock_data_init | ( | THR_LOCK * | lock, |
THR_LOCK_DATA * | data, | ||
void * | param | ||
) |
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_init | ( | THR_LOCK * | lock | ) |
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.
|
inlinestatic |
enum enum_thr_lock_result thr_multi_lock | ( | THR_LOCK_DATA ** | data, |
uint | count, | ||
THR_LOCK_INFO * | owner, | ||
ulong | lock_wait_timeout | ||
) |
void thr_multi_unlock | ( | THR_LOCK_DATA ** | data, |
uint | count | ||
) |
|
static |
void thr_print_locks | ( | void | ) |
void thr_set_lock_wait_callback | ( | void(*)(void) | before_wait, |
void(*)(void) | after_wait | ||
) |
void thr_unlock | ( | THR_LOCK_DATA * | data | ) |
|
static |
|
static |
Wake up all threads which pending requests for the lock can be satisfied.
lock | Lock for which threads should be woken up |
|
static |
|
static |
ulong locks_immediate = 0L |
ulong locks_waited = 0L |
ulong max_write_lock_count = ~(ulong)0L |
LIST* thr_lock_thread_list |
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE |