Table of Contents
Overview
Row lock structure
Table lock structure
Description of locks in transactions
Home Database Mysql Tutorial What is the internal implementation mechanism of Mysql lock?

What is the internal implementation mechanism of Mysql lock?

Jun 03, 2023 pm 06:04 PM
mysql

Overview

Although modern relational databases are increasingly similar, they may have completely different mechanisms behind their implementation. In terms of actual use, because of the existence of SQL syntax specifications, it is not difficult for us to be familiar with multiple relational databases, but there may be as many lock implementation methods as there are databases.

Microsoft Sql Server only provided page locks before 2005. It was not until the 2005 version that it began to support optimistic concurrency and pessimistic concurrency. Optimistic mode allows row-level locks to be implemented. In the design of Sql Server, locks are a scarce resource. Locks The greater the number, the greater the overhead. In order to avoid a cliff-like drop in performance due to the rapid increase in the number of locks, it supports a mechanism called lock upgrade. Once the row lock is upgraded to a page lock, the concurrency performance will return to the original point. .

In fact, there are still many disputes about the interpretation of locking functions by different execution engines in the same database. MyISAM only supports table-level locking, which is fine for concurrent reading, but has certain limitations in concurrent modification. Innodb is very similar to Oracle, providing non-locking consistent reading and row lock support. The obvious difference from Sql Server is that as the total number of locks increases, Innodb only needs to pay a small price.

Row lock structure

Innodb supports row locks, and there is no particularly large overhead in describing the locks. Therefore, there is no need for a lock upgrade mechanism as a rescue measure after a large number of locks cause performance degradation.

Excerpted from the lock0priv.h file, Innodb defines row locks as follows:

/** Record lock for a page */
struct lock_rec_t {
    /* space id */
    ulint  space;	
    /* page number */
    ulint  page_no;
    /**
     * number of bits in the lock bitmap; 
     * NOTE: the lock bitmap is placed immediately after the lock struct 
     */
    ulint  n_bits;			
};
Copy after login

Although concurrency control can be refined at the row level, the lock management method is organized in units of pages. of. In the design of Innodb, the only data page can be determined through the two necessary conditions of space id and page number. n_bits indicates how many bits are needed to describe the row lock information of the page.

Each record in the same data page is assigned a unique continuous increasing sequence number: heap_no. If you want to know whether a certain row of records is locked, you only need to determine whether the number in the heap_no position of the bitmap is one. Since the lock bitmap allocates memory space based on the number of records in the data page, it is not explicitly defined, and the page records may continue to increase, so a space of LOCK_PAGE_BITMAP_MARGIN size is reserved.

/** 
 * Safety margin when creating a new record lock: this many extra records
 * can be inserted to the page without need to create a lock with 
 * a bigger bitmap
 */
#define LOCK_PAGE_BITMAP_MARGIN	 64
Copy after login

Assume that the data page with space id = 20, page number = 100 currently has 160 records, and the records with heap_no of 2, 3, and 4 have been locked, then the corresponding lock_rec_t structure and data page should be like this Depiction:

What is the internal implementation mechanism of Mysql lock?

Note:

  • The lock bitmap in the memory should be linearly distributed. The two-dimensional structure shown in the figure is In order to facilitate the description

  • bitmap and lock_rec_t structures are a continuous memory, and the reference relationship in the figure is also required for drawing

You can see the corresponding page The second, third, and fourth positions of the bitmap are all set to 1. The memory consumed by describing a data page row lock is quite limited from the perspective of perception. How much does it occupy specifically? We can calculate:

160 / 8 8 1 = 29byte.

  • 160 records correspond to 160bit

  • 8 is because 64bit needs to be reserved

  • 1 This is because 1 byte is reserved in the source code

In order to avoid the problem of small result values, an additional 1 is added here. This can avoid errors caused by integer division. If there are 161 records, if it is not 1, the calculated 20 bytes are not enough to describe the lock information of all records (without using reserved bits).

Excerpted from the lock0priv.h file:

/* lock_rec_create函数代码片段 */
n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
n_bytes = 1 + n_bits / 8;
/* 注意这里是分配的连续内存 */
lock = static_cast<lock_t*>(
    mem_heap_alloc(trx->lock.lock_heap, sizeof(lock_t) + n_bytes)
);
/**
 * Gets the number of records in the heap.
 * @return number of user records 
 */
UNIV_INLINE ulint page_dir_get_n_heap(const page_t* page)	
{
    return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
}
Copy after login

Table lock structure

Innodb also supports table locks. Table locks can be divided into two categories: intention locks and auto-increment locks. The data structure is defined as follows:

Extracted from the lock0priv.h file

struct lock_table_t {
    /* database table in dictionary cache */
    dict_table_t*  table;
    /* list of locks on the same table */
    UT_LIST_NODE_T(lock_t)  locks;
};
Copy after login

Excerpted from the ut0lst.h file

struct ut_list_node {
    /* pointer to the previous node, NULL if start of list */
    TYPE*  prev;
    /* pointer to next node, NULL if end of list */
    TYPE*  next;
};
#define UT_LIST_NODE_T(TYPE)  ut_list_node<TYPE>
Copy after login

Description of locks in transactions

The above lock_rec_t, lock_table_t The structure is just a separate definition. The lock is generated in the transaction. Therefore, the row lock and table lock corresponding to each transaction will have a corresponding lock structure. Its definition is as follows:

Excerpted from the lock0priv.h file

/** Lock struct; protected by lock_sys->mutex */
struct lock_t {
    /* transaction owning the lock */
    trx_t*  trx;
    /* list of the locks of the transaction */
    UT_LIST_NODE_T(lock_t)  trx_locks;	
    /** 
     * lock type, mode, LOCK_GAP or LOCK_REC_NOT_GAP,
     * LOCK_INSERT_INTENTION, wait flag, ORed 
     */
    ulint  type_mode;
    /* hash chain node for a record lock */
    hash_node_t  hash;	
    /*!< index for a record lock */
    dict_index_t*  index;
    /* lock details */
    union {
        /* table lock */
        lock_table_t  tab_lock;
        /* record lock */
        lock_rec_t  rec_lock;
    } un_member;
};
Copy after login

lock_t is defined based on each page (or table) of each transaction, but a transaction often involves multiple pages, so the linked list trx_locks is needed to concatenate all the lock information related to a transaction. In addition to querying all lock information based on transactions, the actual scenario also requires that the system must be able to quickly and efficiently detect whether a row record has been locked. Therefore, there must be a global variable to support querying lock information for row records. Innodb chose the hash table, which is defined as follows:

Extracted from the lock0lock.h file

/** The lock system struct */
struct lock_sys_t {
    /* Mutex protecting the locks */
    ib_mutex_t  mutex;		
    /* 就是这里: hash table of the record locks */
    hash_table_t*  rec_hash;	
    /* Mutex protecting the next two fields */
    ib_mutex_t  wait_mutex;
    /** 
     * Array  of user threads suspended while waiting forlocks within InnoDB,
     * protected by the lock_sys->wait_mutex 
     */
    srv_slot_t*  waiting_threads;
    /*
     * highest slot ever used in the waiting_threads array,
     * protected by lock_sys->wait_mutex 
     */
    srv_slot_t*  last_slot;
    /** 
     * TRUE if rollback of all recovered transactions is complete. 
     * Protected by lock_sys->mutex 
     */
    ibool  rollback_complete;
    /* Max wait time */
    ulint  n_lock_max_wait_time;
    /**
     * Set to the event that is created in the lock wait monitor thread.
     * A value of 0 means the thread is not active
     */
    os_event_t	timeout_event;		
    /* True if the timeout thread is running */
    bool  timeout_thread_active;
};
Copy after login

The function lock_sys_create is responsible for initializing the lock_sys_t structure when the database starts. The srv_lock_table_size variable determines the size of the number of hash slots in rec_hash. The key value of the rec_hash hash table is computed by using the space id and page number of the page..

Excerpted from lock0lock.ic, ut0rnd.ic files

/**
 * Calculates the fold value of a page file address: used in inserting or
 * searching for a lock in the hash table.
 *
 * @return folded value 
 */
UNIV_INLINE ulint lock_rec_fold(ulint space, ulint page_no)
{
    return(ut_fold_ulint_pair(space, page_no));
}
/**
 * Folds a pair of ulints.
 *
 * @return folded value 
 */
UNIV_INLINE ulint ut_fold_ulint_pair(ulint n1, ulint n2)
{
    return (
        (
            (((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)
            ^ UT_HASH_RANDOM_MASK
        ) 
        + n2
    );
}
Copy after login

This will mean that there is no way to provide a way for us to directly know whether a certain row is locked. Instead, you should first obtain the space id and page number through the page where it is located, obtain the key value through the lock_rec_fold function, and then obtain lock_rec_t through hash query, and then scan the bit map according to heap_no to finally determine the lock information. The lock_rec_get_first function implements the above logic:

这里返回的其实是lock_t对象,摘自lock0lock.cc文件

/**
 * Gets the first explicit lock request on a record.
 *
 * @param block   : block containing the record 
 * @param heap_no : heap number of the record 
 *
 * @return first lock, NULL if none exists 
 */
UNIV_INLINE lock_t* lock_rec_get_first(const buf_block_t* block, ulint heap_no)
{
    lock_t*  lock;
    ut_ad(lock_mutex_own());
    for (lock = lock_rec_get_first_on_page(block); lock;
         lock = lock_rec_get_next_on_page(lock)
    ) {
        if (lock_rec_get_nth_bit(lock, heap_no)) {
            break;
        }
    }
    return(lock);
}
Copy after login

以页面为粒度进行锁维护并非最直接有效的方式,它明显是时间换空间,不过这种设计使得锁开销很小。某一事务对任一行上锁的开销都是一样的,锁数量的上升也不会带来额外的内存消耗。

对应每个事务的内存对象trx_t中,包含了该事务的锁信息链表和等待的锁信息。因此存在如下两种途径对锁进行查询:

  • 根据事务: 通过trx_t对象的trx_locks链表,再通过lock_t对象中的trx_locks遍历可得某事务持有、等待的所有锁信息。

  • 根据记录: 根据记录所在的页,通过space id、page number在lock_sys_t结构中定位到lock_t对象,扫描bitmap找到heap_no对应的bit位。

上述各种数据结构,对其整理关系如下图所示:

What is the internal implementation mechanism of Mysql lock?

注:

lock_sys_t中的slot颜色与lock_t颜色相同则表明lock_sys_t slot持有lock_t 指针信息,实在是没法连线,不然图很混乱

The above is the detailed content of What is the internal implementation mechanism of Mysql lock?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1664
14
PHP Tutorial
1269
29
C# Tutorial
1249
24
MySQL's Role: Databases in Web Applications MySQL's Role: Databases in Web Applications Apr 17, 2025 am 12:23 AM

The main role of MySQL in web applications is to store and manage data. 1.MySQL efficiently processes user information, product catalogs, transaction records and other data. 2. Through SQL query, developers can extract information from the database to generate dynamic content. 3.MySQL works based on the client-server model to ensure acceptable query speed.

Laravel Introduction Example Laravel Introduction Example Apr 18, 2025 pm 12:45 PM

Laravel is a PHP framework for easy building of web applications. It provides a range of powerful features including: Installation: Install the Laravel CLI globally with Composer and create applications in the project directory. Routing: Define the relationship between the URL and the handler in routes/web.php. View: Create a view in resources/views to render the application's interface. Database Integration: Provides out-of-the-box integration with databases such as MySQL and uses migration to create and modify tables. Model and Controller: The model represents the database entity and the controller processes HTTP requests.

MySQL and phpMyAdmin: Core Features and Functions MySQL and phpMyAdmin: Core Features and Functions Apr 22, 2025 am 12:12 AM

MySQL and phpMyAdmin are powerful database management tools. 1) MySQL is used to create databases and tables, and to execute DML and SQL queries. 2) phpMyAdmin provides an intuitive interface for database management, table structure management, data operations and user permission management.

MySQL vs. Other Programming Languages: A Comparison MySQL vs. Other Programming Languages: A Comparison Apr 19, 2025 am 12:22 AM

Compared with other programming languages, MySQL is mainly used to store and manage data, while other languages ​​such as Python, Java, and C are used for logical processing and application development. MySQL is known for its high performance, scalability and cross-platform support, suitable for data management needs, while other languages ​​have advantages in their respective fields such as data analytics, enterprise applications, and system programming.

Solve database connection problem: a practical case of using minii/db library Solve database connection problem: a practical case of using minii/db library Apr 18, 2025 am 07:09 AM

I encountered a tricky problem when developing a small application: the need to quickly integrate a lightweight database operation library. After trying multiple libraries, I found that they either have too much functionality or are not very compatible. Eventually, I found minii/db, a simplified version based on Yii2 that solved my problem perfectly.

Laravel framework installation method Laravel framework installation method Apr 18, 2025 pm 12:54 PM

Article summary: This article provides detailed step-by-step instructions to guide readers on how to easily install the Laravel framework. Laravel is a powerful PHP framework that speeds up the development process of web applications. This tutorial covers the installation process from system requirements to configuring databases and setting up routing. By following these steps, readers can quickly and efficiently lay a solid foundation for their Laravel project.

MySQL for Beginners: Getting Started with Database Management MySQL for Beginners: Getting Started with Database Management Apr 18, 2025 am 12:10 AM

The basic operations of MySQL include creating databases, tables, and using SQL to perform CRUD operations on data. 1. Create a database: CREATEDATABASEmy_first_db; 2. Create a table: CREATETABLEbooks(idINTAUTO_INCREMENTPRIMARYKEY, titleVARCHAR(100)NOTNULL, authorVARCHAR(100)NOTNULL, published_yearINT); 3. Insert data: INSERTINTObooks(title, author, published_year)VA

Solve MySQL mode problem: The experience of using the TheliaMySQLModesChecker module Solve MySQL mode problem: The experience of using the TheliaMySQLModesChecker module Apr 18, 2025 am 08:42 AM

When developing an e-commerce website using Thelia, I encountered a tricky problem: MySQL mode is not set properly, causing some features to not function properly. After some exploration, I found a module called TheliaMySQLModesChecker, which is able to automatically fix the MySQL pattern required by Thelia, completely solving my troubles.

See all articles