Database transaction (two)------Mysql database lock

We have already understood the database transaction isolation level dirty read, virtual read, non-repeatable read, but if we want to better operate the database and improve the performance of database read and write, we also need to understand another mechanism of the database --- database lock!

In fact, partners who have just used mysql database for a long time may have no idea about database locks, and they may still have questions. Is the database deadlocked? Haven't seen it before. If the database is deadlocked, isn't it GG? The first thing to confirm is that of course the database will deadlock. Since there are transactions, isolation, and concurrency, once the logic is not handled well, deadlocks will definitely occur.

As for most of the small partners who have not encountered it, one is because the business concurrency you may be exposed to is not particularly high, the business logic is not particularly complicated, and another important reason is that there is a deadlock monitoring mechanism inside the database. Once the database is found to be dead Lock, it will trigger the rollback operation, will not make the database really down.

Let's get to know the lock of the database. Since it is data isolation, operating data under high concurrency must be locked, otherwise it will be messed up. When we get to know the lock, the deadlock mechanism is very simple for us, and you can easily write a deadlock business operation, just like using java code to achieve a deadlock, hehe.

We know that the locks in java (common) are generally optimistic locks (CAS), the locks implemented by inheriting AQS are implemented by blocking pairing, and there are locks implemented by Synchronized monitors. What about MySQL? Java is a language, which is mainly aimed at locking the data logic or the resources needed to run the program. The main lock is the resource, but what about the MySQL database? This is a relational database, where the lock is mainly to lock the data to prevent events such as dirty reads, so there must be a difference between the two locks.

Let's take a look at MySQL locks, mainly row locks (Record Locks), gap locks (proximal key locks), intention locks (Insert Intention Locks), auto-inc Locks, etc., let's expand on .

1. Row lock

Let's create a data table first, so that it will be clearer by looking at the operation. The following is the sql statement to build a table and a few pieces of data.

CREATE TABLE `student`  (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id主键',
  `age` int(11) NULL DEFAULT NULL COMMENT '年龄',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '名称',
  `id_card` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '身份证号',
  `stage` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '等级',
  `create_date` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `idx_card`(`id_card`) USING BTREE COMMENT '唯一索引--身份编号',
  INDEX `idx_stage`(`stage`) USING BTREE COMMENT '普通索引--等级索引'
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '个人测试索引-学生表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, 16, '张三', '110120200402023456', '9', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (2, 16, '张三加', '110120200402023454', '9', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (3, 16, '张四', '110120200402023457', '8', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (4, 16, '张五', '110120200402023458', '7', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (5, 16, '张六', '110120200402023459', '6', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (6, 16, '张七', '110120200402023460', '5', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (7, 16, '张八', '110120200402023465', '4', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (8, 16, '张九', '110120200402023466', '15', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (9, 16, '张氏', '110120200402023467', '16', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (10, 16, '李四', '110120200402023480', '18', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (11, 16, '李五', '110120200402023481', '19', '2020-10-21 14:07:15');
INSERT INTO `student` VALUES (12, 16, '李六', '110120200402023482', '20', '2020-10-21 14:07:15');

Cut a picture, look at it clearly~

mysql student data table, unique index id_card​​, ordinary index stage

Before we talk about unlocking, let's first understand the view of the isolation level, which is the following statement:

select @@tx_isolation as the current isolation level, @@global.tx_isolation as the global isolation level; 
the isolation level of the transaction has an impact on the lock. Before performing the lock operation, it is recommended that you check the isolation level of the transaction. Of course, MySQL The default is REPEATABLE-READ

Well, let's take a look at these sql statements.

-- 开启事务A 
START TRANSACTION;
-- id=7的数据 
SELECT * FROM student where id=7 for UPDATE;  
-- --上半部分
-- ----------
-- --下半部分
ROLLBACK;

-- ----最好在可视化工具的两个查询页面,方便看结果

-- 启动事务B
START TRANSACTION ;
-- id=7的数据 
SELECT * FROM student where id=7 for UPDATE;  

-- --上半部分
-- ----------
-- --下半部分
ROLLBACK;

       We know that adding for update after the query statement is to add an intention lock to the entire student table (described below), and then add an exclusive lock to the record with id=7, which locks the result data of the query. In fact, it is obvious that for update (for modification) you want to modify it, and you must not allow other people to modify it, otherwise the modification together will not mess up the set.

When we run the upper half of transaction A, the data with id=7 is locked, and transaction A has not ended. Then start transaction B and query Li Si again (for update). We will find that Li Si’s data cannot be queried. The transaction has been running and there is no error message. In fact, it is waiting, waiting for the end of transaction A (submit or return). roll). Of course, if transaction B queries the data with id=8, there is definitely no problem .

In fact, at this time, the row lock is added to the data with id=7.

Let's look at the official description of the down lock A record lock is a lock on an  index record ( row lock must be used on the index ).       

The id of the student table (clustered index was added when the table was built), idx_card, and idx_stage are all indexed. If the lock operation is performed under these conditions, this piece of data will be locked.

There are two types of row locks:

  • Shared lock (S)  Shared lock is also called read lock. Read lock allows multiple connections to read the same resource concurrently at the same time without interfering with each other;

  • Exclusive lock (X)  Exclusive lock is also called write lock. A write lock will block other write locks or read locks, ensuring that only one connection can write data at the same time, while preventing other users from reading and writing this data.

However, if the condition is that a field such as name is not indexed, and you want to lock a piece of data, you can only use table locks. In this case, it consumes more resources and is prone to deadlock.

2. Gap lock 

We just saw that when querying with index conditions, row locks will be performed. So, what is a gap lock? Let's take a look at the following statements.

-- 开启事务A 
START TRANSACTION;
-- id_card大于'110120200402023465',小于'110120200402023481'的数据 
SELECT * FROM student where id_card>'110120200402023465' and id_card <'110120200402023481' for UPDATE
-- --上半部分
-- ----------
-- --下半部分
ROLLBACK;

-- -----------------------------------------------------------

-- 启动事务B
START TRANSACTION ;
-- 删除 id_card='110120200402023481' 的数据 
DELETE FROM student where id_card='110120200402023481';

-- --上半部分
-- ----------
-- --下半部分
ROLLBACK;

Run the upper half of transaction A, and lock the data whose id_card is greater than '110120200402023465' and less than '110120200402023481'. At this time, id_card is greater than '110120200402023465' and less than '110120200402023481'. This data segment is locked. If you insert id_card= The data of 110120200402023469 must have failed.

But what if you run the upper part of transaction B? id_card is less than '110120200402023481', is '110120200402023481' not locked? Of course not. If you execute the SQL statement, you will find that transaction B has been waiting until transaction A rollback. Transaction B can continue to run. Obviously, the data whose id_card data is '110120200402023481' is locked.

Query related concepts, we will find that the strategy of gap lock locking is left open and right closed. When you lock an interval, the data on the left is not locked, and the data on the right is locked. So the locked interval of transaction A is ('110120200402023465','110120200402023481'], you can try it, transaction B is not locked if id_card=110120200402023465 is operated.

With the gap lock, a certain segment is locked. In this way, some control can actually avoid the occurrence of phantom reads. At the same time, a minimum range of locking is performed to ensure database performance.

Of course, the gap lock is also for the index, and the table is directly locked if there is no index.

3. Intent lock

In order to support multiple granularity locking, which allows row-level locks and table-level locks to coexist, intention locks are introduced. Intentional lock means that at some point in the future, the transaction may need to be shared/exclusively locked, and an intent is declared in advance.

SELECT * FROM student where id_card>'110120200402023465' and id_card <'110120200402023481' for UPDATE

This is actually an intention lock.

  1. Intent lock is a table-level locking (table-level locking);
  2. Intent locks are divided into:
    • Intention shared lock (intention shared lock, IS), it indicates that the transaction intends to add shared S locks to certain rows in the table
    • Intention exclusive lock (IX), it indicates that the transaction intends to add exclusive X locks to certain rows in the table

 grammar:

select ... lock in share mode; To set IS lock;
       select ... for update; To set IX lock;

The following is the mutual exclusion relationship between intention lock and S lock and X lock 

 

 As for the self-increasing lock, I think everyone has used it. Every time we build a table, our id is generally set to self-increment. In fact, a self-increase lock is added here.

Well, the database lock will simply stop here.

No sacrifice,no victory~

Guess you like

Origin blog.csdn.net/zsah2011/article/details/109149721