MySQL solves the problem caused by concurrent transactions - lock

Transaction related: MySQL transaction isolation level and MVCC detailed explanation

1. Lock

Various problems that may arise when transactions are executed concurrently, the situations in which concurrent transactions access the same records can be roughly divided into three types:

  1. Read-read situation: that is, concurrent transactions read the same record successively.
  2. Write-write situation: that is, concurrent transactions make changes to the same record successively.
  3. Read-write or write-read situation: that is, one transaction performs a read operation and the other performs a modification operation.

1. Dirty write problem

Dirty writes occur in write-write situations, which are not allowed by any isolation level. Therefore, when multiple uncommitted transactions make changes to a record in succession, they need to be queued for execution . This queuing process is actually done byLockto be realized. This so-called lock is actually astructure in memory. There is no lock before the transaction is executed, that is to say, there is no lock structure associated with the record at the beginning, as shown in the figure: insert image description hereWhen a transaction wants to make changes to this record, it will first check whether there is any memory related to this record. record associatedlock structure, when there is no lock structure will be generated in memory associated with it.
insert image description here
There is a lot of information in the lock structure, but in order to simplify the understanding, we only take out two more important properties:

  • trx information: Represents which transaction generated this lock structure.
  • is_waiting : Represents whether the current transaction is waiting.

As shown in the figure above, when transaction T1 changes this record, a lock structure is generated to associate with this record, because no other transaction has locked this record before, so the is_waiting attribute is false (the lock was acquired successfully, or Locked successfully).

If another transaction T2 also wants to make changes to the record before the transaction T1 commits, first check to see if there is a lock structure associated with this record, and find that there is a lock structure associated with it, then T2 also generates a lock structure. The lock structure is associated with this record, but the value of the is_waiting attribute of the lock structure is true, indicating that the current transaction needs to wait (failure to acquire the lock, or failure to acquire the lock, or unsuccessful acquisition of the lock)
insert image description here
. The lock structure generated by the transaction is released, and then see if there are other transactions waiting to acquire the lock. It is found that transaction T2 is still waiting to acquire the lock, so set the is_waiting attribute of the lock structure corresponding to transaction T2 to false, and then set The thread corresponding to the transaction wakes up and allows it to continue executing. At this time, transaction T2 acquires the lock.

2. Dirty reads, non-repeatable reads, and phantom reads

Dirty reads, non-repeatable reads, and phantom reads may occur in read-write or write-read situations.

There are two solutions to the above problem:

  • Scheme ①: Read operations use multi-version concurrency control (MVCC), and write operations are locked.
    MVCC is to generate a ReadView, and then find the qualified record version through ReadView. The query statement can only read the changes made by the committed transactions before generating the ReadView, and cannot see the changes made by the uncommitted transactions before generating the ReadView or the transactions opened after that. The write operation must be aimed at the latest version of the record, and the historical version of the read record does not conflict with the latest version of the change record , that is, when MVCC is used, the read-write operation does not conflict.
  • Scheme ②: Both read and write operations are locked.
    Some of our business scenarios do not allow to read the old version of the record, but have to read the latest version of the record every time. In this way, when reading records, they also need to be added, which means that read and write operations are also queued like write-write operations.

If the MVCC method is adopted, the read-write operations do not conflict with each other, and the performance is higher.

3. Consistent read

The read operation performed by a transaction using MVCC is called a consistent read, or a consistent lock-free read, and is also called a snapshot read in some places.

All ordinary SELECT statements are considered consistent reads under the READ COMMITTED and REPEATABLE READ isolation levels. Consistent read does not lock any records in the table, and other transactions are free to make changes to the records in the table.

4. Lock Read

a. Shared locks and exclusive locks

  • Shared Locks for shortS lock. When a transaction wants to read a record, it needs to acquire the S lock of the record first.
  • Exclusive locks, also known as exclusive locks (Exclusive Locks), referred to as ==X lock==. When a transaction wants to change a record, it needs to acquire the X lock of the record first.

If transaction T1 first acquires the S lock on a record, then transaction T2 also needs to access this record. If transaction T2 wants to acquire an S lock on another record, then transaction T2 will also acquire the lock, which means that transactions T1 and T2 hold an S lock on the record at the same time. If transaction T2 wants to acquire another record X lock, then this operation will be blocked until the S lock is released after transaction T1 commits.

If transaction T1 first acquires the X lock of a record, then whether transaction T2 then wants to acquire the S lock or X lock of the record will be blocked until transaction T1 commits.

b. Statements that lock reads

  • Add S lock to the read record:
SELECT ... LOCK IN SHARE MODE;

If the current transaction executes the statement, it will add S lock to the read records, which allows other transactions to continue to acquire the S lock of these records, but cannot acquire the X lock of these records. If other transactions want to acquire X locks on these records, they will block until the S locks on these records are released after the current transaction commits.

  • Add X lock to the read record:
SELECT ... FOR UPDATE;

If the current transaction executes the statement, it will add X locks to the records read, so that neither other transactions are allowed to acquire the S locks of these records, nor the X locks of these records. If other transactions want to acquire S locks or X locks on these records, they will block until the X locks on these records are released after the current transaction commits.

The commonly used write operations are nothing more than DELETE, UPDATE, and INSERT.

Under normal circumstances, the operation of inserting a new record is not locked, and the implicit lock can protect the newly inserted record from being accessed by other transactions before the transaction is committed.

2. Multi-granularity lock

The locks we mentioned earlier are all for records, and can also be called row-level locks or row locks. Locking a record only affects this record. We say that the granularity of this lock is relatively fine. In fact, a transaction can also be locked at the table level, which is naturally called a table-level lock or a table lock. Locking a table affects the records in the entire table. We say that the granularity of this lock is relatively coarse.

  • Add S lock to the table:
    If a transaction adds S lock to the table,
    then:
    other transactions can continue to obtain the S lock of the table
    Other transactions can continue to obtain the S lock of some records in the table
    Other transactions cannot Continue to obtain the X lock of the table
    Other transactions cannot continue to obtain the X lock of some records in the table
  • Add X lock to the table:
    If a transaction adds X lock to the table (meaning that the transaction wants to monopolize the table),
    then:
    other transactions cannot continue to obtain the S lock of the table. Other transactions cannot continue to obtain the S lock
    of the table. S locks on some records of the table Other transactions cannot continue to obtain
    X locks on the table
    Other transactions cannot continue to obtain X locks on some records in the table

Example:

  1. The school has to occupy the teaching building for examinations. At this time, it is not allowed to have classrooms that are studying (reading) in the teaching building, nor is it allowed to carry out maintenance (writing) on ​​the classrooms. So you can place an X lock at the entrance of the teaching building (similar to the table-level X lock)
  2. There are leaders who want to visit the environment of the teaching building. The school leaders considered that they did not want to affect the students' self-study, but at this time, no classrooms could be under maintenance, so an S lock (similar to the table-level S lock) could be placed at the entrance of the teaching building.

Question: When we lock the whole teaching building (table lock), how do we know whether any classrooms in the teaching building have been locked (row lock)?
Answer: Through Intention Locks

  • Intention Shared Lock (Intention Shared Lock)IS lock. When a transaction is going to add an S lock to a record, it needs to add an IS lock at the table level first.
  • Intention Exclusive Lock (Intention Exclusive Lock)IX lock. When a transaction is going to add an X lock on a record, it needs to add an IX lock at the table level first.

Back to the above example:

  • If there is a leader who wants to visit the teaching building, that is, when they want to put an S lock (table lock) in front of the door of the teaching building, they should first check whether there is an IX lock at the door of the teaching building. After the IX lock is removed, the S lock can be added to the entire teaching building.
  • If there is an exam to occupy the teaching building, that is, when you want to put an X lock (table lock) in front of the door of the teaching building, first check whether there is an IS lock or IX lock at the door of the teaching building. If there is, it means that there is a classroom in the self-study Or for maintenance, it is necessary to wait until the students have finished their self-study and after the maintenance is completed and the IS locks and IX locks are removed, then the X locks can be added to the entire teaching building.

IS and IX locks are table-level locks. They are only proposed to quickly determine whether the records in the table are locked when adding table-level S locks and X locks later , so as to avoid using traversal to check whether there are any records in the table. Locked records, that is to say, IS locks are compatible with IX locks, and IX locks are compatible with IX locks.

For storage engines such as MyISAM, MEMORY, and MERGE, they only support table-level locks , and these engines do not support transactions, so the locks using these storage engines are generally for the current session. The InnoDB storage engine supports both table locks , also supports row locks.

3. Locks in the InnoDB storage engine

1. Table-level locks

When executing SELECT, INSERT, DELETE, and UPDATE statements on a table, the InnoDB storage engine will not add table-level S locks or X locks to the table.

When executing some DDL statements such as ALTER TABLE and DROP TABLE on a table, other transactions will block concurrently executing statements such as SELECT, INSERT, DELETE, UPDAT on the table. When a table executes SELECT, INSERT, DELETE, UPDAT statements, the execution of DDL statements on this table in other sessions will also block.

This process is actually done by using the server layermetadata lock(Metadata Locks, MDL for short) is implemented by the East, and generally does not use the table-level S locks and X locks provided by the InnoDB storage engine itself.

The table-level S lock or X lock provided by the InnoDB storage engine is quite tasteless, and is only used in some special cases, such as during crash recovery.

2*. Row level lock

Row-level locks, also known as record locks, are locks on records.

Types of row locks:

  1. LOCK_REC_NOT_GAP
    The record lock we mentioned earlier is this type, that is, only one record is locked . LOCK_REC_NOT_GAP lock is divided into X lock and S lock.
  2. LOCK_GAP
    is only to prevent insertion of ghost records. If you add a LOCK_GAP lock to a record (whether it is a shared LOCK_GAP lock or an exclusive LOCK_GAP lock), it will not restrict other transactions from adding LOCK_REC_NOT_GAP or continuing to add LOCK_GAP locks to this record.
    As shown in the figure, a gap lock is added to the record with the number value of 8, which means that other transactions are not allowed to be in front of the record with the number value of 8.gapInserting a new record is actually the value of the number column (3, 8). New records in this interval are not allowed to be inserted immediately. For example, another transaction wants to insert a new record with a number value of 4. It locates the next record of the new record with a number value of 8, and there is a gap lock on this record, so it will block. Insert operation, until the transaction that owns the gap lock is committed, new records with the value of the number column in the range (3, 8) can be inserted. insert image description here
    Question: Adding a gap lock to a record just does not allow other transactions to insert new records into the gap before this record. What about the gap after the last record, that is, the gap after the record with the number value of 20 in the hero table? What to do?
    A: The data page has two pseudo records: the Infimum record, which represents the smallest record in the page. Supremum record, representing the largest record in the page.
    In order to prevent other transactions from inserting new records whose number value is in the interval (20, +∞), we can add a LOCK_GAP to the Supremum record of the page where the last record in the index, that is, the record with the number value of 20. Lock.
    insert image description here
  3. LOCK_ORDINARY
    not only locks a record, but also prevents other transactions from inserting new records in the gap before the record. (including LOCK_GAP and LOCK_REC_NOT_GAP)
  4. LOCK_INSERT_INTENTION When
    a transaction inserts a record, it needs to determine whether the insertion position is a so-called LOCK_GAP lock by another transaction. If so, the insertion operation needs to wait. The transaction also needs to generate a lock structure in memory while waiting, indicating that a transaction wants to insert a new record in a certain gap, but is now waiting. (Essentially, the is_waiting attribute of the lock structure corresponding to the insertion intention lock is set to true)
  5. Implicit lock
    A transaction can not explicitly lock the newly inserted record (generate a lock structure), but due to the existence of the transaction id, it is equivalent to adding an implicit lock. When other transactions add S lock or X lock to this record, due to the existence of implicit locks, they will first help the current transaction to generate a lock structure, and then generate a lock structure by themselves and then enter the waiting state.

Next: MySQL solves the problems caused by concurrent transactions - locks - the memory structure of locks

Guess you like

Origin blog.csdn.net/myjess/article/details/115868157