Reference article links: MySQL common seven locks detailed description
MySQL locks and transaction isolation levels
How many locks are available in MySQL?
Seven types of locks are common, and one less common predictive lock
- Record Locks are row-level Locks, pessimistic Locks
- Gap Locks are row-level, pessimistic Locks
- Next-key Locks are row-level, pessimistic Locks
- (Read) Shared /(write) Exclusive Locks are row-level Locks, pessimistic Locks
- Intention Shared Locks/Intention Exclusive Locks are table – level, pessimistic Locks
- Insert Intention Locks are a special type of gap Locks, pessimistic Locks
- Auto-inc Locks are table level Locks
How to divide locks in MySQL?
-
According to the locking granularity of data operations :(locking granularity increases in order)
- 1. Row-level locks
- 2. Lock clearance
- 3. Page-level locks
- 4. The table level lock
-
According to the lock sharing strategy:
- 1. A Shared lock
- 2. The exclusive lock
- 3. Intent to share lock
- 4. Intention exclusive lock
-
From the locking strategy:
- Optimistic locking
- Pessimistic locking
-
Other:
- On the lock
According to the locking granularity of data operations
1. What locks are used by different storage engines?
- Table-level locking is used for MYISAM and MEMORY.
- BDB: Page -level locking or table -level locking. Page locking is adopted by default
- InnoDB supports row-level locking and table-level locking. The default row-level locking is performed
Record Lock (partial write)
Introduction to row-level locking
Row-level locks (record locks) are the most fine-grained type of lock in MySQL. Represents a lock on a single row record that must be applied to an index. Row-level locking can greatly reduce the conflicts of database operations, and its locking granularity is the smallest, but the locking cost is also the largest.
Row-level locks can be divided into:
- A Shared lock
- Exclusive lock
Types of row locks:
- Record Locks: Locks on a single row Record.
- Gap Locks: Gap Locks that lock a range, but not the record itself. For example, lock a=5 and the two ranges before and after it, that is, lock a=3,4,6,7, excluding a=5. The purpose of the GAP lock is to prevent the illusion of two current reads of the same transaction.
- Next-key Locks: Locks a range and Locks the record itself. For example, lock a=5 and two ranges before and after it, that is, lock a=3,4,5,6,7. For the query of rows, this method is used, the main purpose is to solve the illusion problem.
Row-level locking features
Overhead, slow lock, deadlock will occur. The probability of lock conflict is the lowest and the concurrency is the highest.
3. Gap Lock
Clearance Lock
A gap lock locks a range, but does not include the record itself (its lock granularity is larger than the record lock locks the entire row, it is locked in a range of multiple rows, including non-existent data), a gap lock must be open interval, such as (3,5).
The purpose of the GAP lock is to prevent the illusion of two current reads of the same transaction. The lock will only exist at isolation levels RR(repeatable read) or above. The purpose of gap locking is to prevent other transactions from adding data to the gap.
4. Next-key Lock
Key lock introduction
It is a combination of record locking and gap locking, locking a range, and locking the record itself. For the query of rows, this method is used, the main purpose is to solve the illusion problem. Next-key is InnoDB’s default lock. Next-key is an open and closed interval, such as (3,5).
A next-key lock is equivalent to a record lock with a gap lock. When a next-key lock is applied to an index, the record and the interval before it are locked. If you have records 1, 3, 5, 7, and now add a next-key lock to record 5, the interval (3, 5) will be locked, and any attempts to insert into this interval will block.
Record Lock, gap lock, next-key lock, are added to the index. If there are records 1,3,5,7, then the record lock on 5 will lock the gap lock on 5 (3,5), and the next-key lock on 5 (3,5).
Note that the next Key lock specifies the left open and right closed interval!
Name = primary key, id= normal index, id=10, next-key = open, id=6, id=6, id=6, id=10, id=10 That is (6, 10]
5. Table level lock (partial read)
This section describes table locking
Table level lock is the lock with the largest granularity in mysql. It locks the entire table in the current operation. It is simple to implement, consumes less resources, and is supported by most mysql engines. The most commonly used MYISAM and InnoDB both support table-level locking.
Table locks can be divided into:
- Table shared read lock (shared lock)
- Table exclusive write lock (exclusive lock)
Table locking features
Low overhead, fast lock, no deadlocks. The probability of lock conflict is the highest and the concurrency is the lowest.
LOCK TABLE my_table_name READ;
Locking tables with read locks blocks other transactions from modifying table data.LOCK TABLE my_table_name WRITE;
Locking the table with a write lock blocks other transaction reads and writes.
Table level locking in different storage engines
- InnoDB storage engine does not add table level S or X locks to a table when executing SELECT, INSERT, DELETE or UPDATE statements. Table level locks need to be explicitly declared manually.
- MyISAMWhen executing a query (SELECT) will be automatically given to all tables involvedAdd read lock, while performing the update operation (UPDATE, DELETE, INSERTAnd so on) will automatically give the table involvedAdd write lock, this process does not require user intervention, therefore, users generally do not need to directly use
LOCK TABLE
Command to explicitly lock the MYISAM table.
SQL Basic Operations
- Build table SQL:
CREATE TABLE `mylock` (
`id` INT (11) NOT NULL AUTO_INCREMENT,
`NAME` VARCHAR (20) DEFAULT NULL.PRIMARY KEY (`id`)
) ENGINE = MyISAM DEFAULT CHARSET = utf8;
Copy the code
- Insert data:
INSERT INTO`test`.`mylock` (`id`, `NAME`) VALUES ('1'.'a');
INSERT INTO`test`.`mylock` (`id`, `NAME`) VALUES ('2'.'b');
INSERT INTO`test`.`mylock` (`id`, `NAME`) VALUES ('3'.'c');
INSERT INTO`test`.`mylock` (`id`, `NAME`) VALUES ('4'.'d');
Copy the code
- Manually add table locks (read locks/write locks)
lock tableTable name read/Write, table name2 read/write;
Copy the code
- View the locks added to the table
show open tables;
Copy the code
- Delete table locks
unlock tables;
Copy the code
LOCK TABLES t1 READ
: lock S for table T1.LOCK TABLES t1 WRITE
Add table level X lock to table T1.
Try not to use these two ways to lock, because InnoDB’s advantage is row lock, so try to use row lock, performance is higher.
5. Page-level locks
Page-level locking
Page-level locking is a kind of lock whose granularity is between row-level locking and table-level locking in MySQL. Table level locking is fast but has many conflicts, while row level locking is slow but has few conflicts. Therefore, a compromise page-level lock is adopted to lock adjacent sets of records at a time. The BDB engine supports page-level locking by default.
Page-level locking features
The overhead and locking time are between table and row locks. Deadlocks occur; The locking granularity is between table locks and row locks, and the concurrency is average.
According to the lock sharing policy
Shared lock and exclusive lock in MySQL specific implementation is read lock and write lock:
- Read Locks: Shared Locks (S Locks) allow multiple read operations to be performed simultaneously for the same data without affecting each other
- Write Locks: Exclusive Locks that block other write and read Locks until the current write operation is complete
- IS Lock: Intention Shared Lock When a transaction IS about to place an S lock on a record, an IS lock needs to be placed at the table level.
- IX Lock: Intention Exclusive Lock. When a transaction is about to place an X lock on a record, an IX lock is required at the table level.
IS and IX locks are table-level locks. They are proposed only to quickly determine whether the records in the table are locked when the S-level locks and X-level locks are added later, so as to avoid traversing to check whether there are locked records in the table. When a row is locked, if you want to add a table lock to the table where the row resides, you must first check whether the row is locked, otherwise there will be conflicts. IS and IX locks eliminate the need to traverse each row in a table to determine whether the row IS locked or not. You can determine whether a table has a row lock by checking whether the table has an intent lock.
Note: If there are more than one row lock in a table, they all add an intent lock to the table. There is no conflict between the intent lock and the intent lock.
1. Shared lock/exclusive lock
Shared/exclusive locks are only row locks, not gap locks.
- A shared lock is a lock held by a transaction that concurrently reads a row of records. For the same data, multiple read operations can be performed simultaneously without affecting each other.
- Exclusive locks are the locks that a transaction needs to hold to update or delete a row concurrently. Before the current write operation is complete, it blocks other write locks and read locks.
Read locks block writes, but not reads. Write locks block both reads and writes from other threads.
2. Intentional shared lock/intentional exclusive lock
Intentional shared lock/intentional exclusive lock belongs to table lock, and obtaining intentional shared lock/intentional exclusive lock is the prerequisite of obtaining shared lock/exclusive lock.
- (IS) Intention Shared Lock: When a transaction intends to place an S Lock on a record, it needs to place an IS Lock on the table level.
- When a transaction intends to place an X Lock on a record, an IX Lock needs to be placed at the table level.
IS and IX locks are table-level locks. They are proposed only to quickly determine whether the records in the table are locked when the S-level locks and X-level locks are added later, so as to avoid traversing to check whether there are locked records in the table. When a row is locked, if you want to add a table lock to the table where the row resides, you must first check whether the row is locked, otherwise there will be conflicts. IS and IX locks eliminate the need to traverse each row in a table to determine whether the row IS locked or not. You can determine whether a table has a row lock by checking whether the table has an intent lock.
Shared/exclusive locks are compatible with intentional shared/intentional exclusive locks:
X | IX | S | IS | |
---|---|---|---|---|
X | The mutex | The mutex | The mutex | The mutex |
IX | The mutex | Compatible with | The mutex | Compatible with |
S | The mutex | The mutex | Compatible with | Compatible with |
IS | The mutex | Compatible with | Compatible with | Compatible with |
These four types of locks are pessimistic locks. If there are multiple rows in a table, they will add intent locks to the table. There will be no conflict between intent locks, and exclusive locks will conflict with everyone.
3. Insert intent lock (IIX)
Insert intention lock is a special gap lock, but unlike gap lock, this lock is only used for concurrent insert operations. If a gap lock locks an interval, then an insert intent lock locks a point.
Another very important difference from a gap lock is that although an intention lock is a gap lock, two transactions cannot have a gap lock at the same time and the other has an intention lock within that gap interval (of course, it is possible to have an intention lock if it is not within a gap interval). Let’s review shared and exclusive locks again: shared locks are used for read operations, while exclusive locks are used for update or delete operations. That is to say, insert intention lock, shared lock and exclusive lock cover the commonly used add, delete, change, check four actions.
From the lock strategy points: optimistic lock and pessimistic lock
1. The pessimistic locking
Pessimistic lock thinks that for the concurrent operation of the same data, it must be modified (add, delete, change more, search less), even if there is no modification, it will be considered modified. Therefore, for concurrent operations on the same data, pessimistic locking takes the form of locking. The pessimistic view is that concurrent operations without locking are bound to cause problems.
Pessimistic locking uses the row lock of the database. It believes that the database will have a concurrent conflict, and the data will be directly locked, and other transactions cannot be modified until the current transaction is committed.
2. Optimistic locking
Optimistic locks assume that concurrent operations on the same data will not change (add, delete, change less, search more). When data is updated, it is modified by constantly trying to update the data. If there is no conflict, the operation succeeds. If there is a conflict, another thread is already using the resource, so the polling is continued. Optimistically, concurrency without locking is fine. Optimistic locking is the practice of recording multiple versions of a data history, and then returning to the unmodified version if any conflicts are found after modification. The upside is reduced context switching, the downside is wasted CPU time.
Optimistic locking, compared with pessimistic locking, considers that data will not cause conflicts in general. Therefore, when data is submitted for update, it will formally check whether data conflicts. If conflicts are found, an error message will be returned to let the user decide what to do.
Optimistic locking is the idea that data will be updated if it is not locked, and not updated if something is wrong (rollback). This is often done by adding a Version field (version number) to the database. Optimistic locks can be used to avoid lost updates. Let’s look at the implementation of optimistic locking in tables and caches.
Implementation in optimistic lock data table
The version mechanism is one of the most common implementations of optimistic locking. Generally, a version field of numeric type is added to the database table. When data is read, the value of the Version field is read together. Each time the data is updated, the version value is +1. When we submit the update, compare the current version information of the database table with the version value extracted for the first time. If the current version number of the database table is equal to the version value extracted for the first time, it will be updated; otherwise, it is considered as expired data and the update fails.
Example:
-- Step1: Query commodity information
select (quantity,version) from items where id=100;
-- Step2: Generate orders according to commodity information
insert into orders(id,item_id) values(null.100);
Step3: Modify the inventory of goods
update items set quantity=quantity- 1,version=version+1 where id=100 and version=#{version};
Copy the code
Since you can use the version, that you can also use the timestamp field, this method is also add a timestamp field in the table, and the above version of similar, also check the current data in the database when updates to submit the update timestamp and his former were compared to a timestamp, if the agreement is OK, otherwise it is version conflict.
It is important to note that if your data table is a read-write separated table, whenmasterData written to the table is not synchronized in timeslaveThe update fails all the time. At this point, you need to force a readmasterThe data in the table (willselectStatements inThe transaction).That is:theselectThe statement is placed in the transaction and the query ismasterThe main library!
The lock granularity of optimistic locks
Optimistic locks are widely used for state synchronization. We often encounter a scenario where the state of a logistics order is changed simultaneously, so optimistic locks play a huge role in this situation. However, the selection of optimistic lock field also needs to be very careful, a good optimistic lock field can reduce the lock granularity.
In the case of commodity inventory deduction, especially in high concurrency scenarios such as seckilling and juhuaxan, if version number is used as optimistic lock, only one transaction can be updated successfully every time, which means a large number of operations fail in business perception. Because the granularity of version is too large, the probability of update failure increases.
But if we pick the inventory field as an optimistic lock (comparing the inventory number to determine the version of the data), then our lock granularity will be reduced and the probability of update failure will be greatly reduced.
-- Use inventory as optimistic lock
-- Step1: Query commodity information
select (inventory) from items where id=100;
-- Step2: Generate orders according to commodity information
insert into orders(id,item_id) values(null.100);
Step3: Modify the inventory of goods
update items set inventory=inventory- 1 where id=100 and inventory- 1>0;
Copy the code
Taobao seconds kill, ju cost-effective, run is this SQL, through the selection of optimistic lock, can reduce the lock strength, so as to improve throughput.
Others: Auto-add lock auto-inc
Auto-inc lock
- An auto-Inc lock is added at the table level when the insert statement is executed, then increments are allocated for each AUTO_INCREMENT column of the record to be inserted, and the auto-Inc lock is released at the end of the insert statement. Such a transaction holds the auto-Inc lock, and inserts of other transactions are blocked, ensuring that increments allocated in a statement are continuous.
- Add AUTO_INCREMENT (int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int, int int);
System variable Innodb_autoinc_lock_mode:
- Innodb_autoinc_lock_mode if the value is 0, auto-inc lock is used.
- Innodb_autoinc_lock_mode value is 2: lightweight lock is used.
- When innodb_autoINC_LOCK_mode is 1, auto-inc lock is used when the number of insert records is uncertain, and lightweight lock is used when the number of insert records is certain
The auto-increment lock is a special table-level lock that is mainly used to insert auto-increment fields in transactions, which is the most commonly used auto-increment primary key ID. The innodb_autoinc_lock_mode parameter is used to set the generation policy of the autoincrement primary key. This prevents errors in the automatic id increment during concurrent data insertion.
When a column in a table is autoincrement, InnoDB adds an exclusive lock to the end of the index. In order to access this incrementing value, a table-level lock is required, but this table-level lock is only for the duration of the current SQL, not the entire transaction, i.e., when the current SQL is executed, the table-level lock is released. Other threads cannot insert any records while the table level lock is held.