Interviewer: How to solve the MySQL deadlock problem?

insert image description here

row lock in mysql

Before analyzing deadlocks, let's recall row locks in MySQL. MySQL has the following three types of row locks. This section only briefly introduces them. If you want to know more about them, see my other articles

Record Lock: Lock a single record
insert image description here
Gap Lock: Lock the gap in front of the record and do not allow records to be inserted
insert image description here

Next-key Lock: Locks the data and the gap in front of the data at the same time, that is, neither the data nor the gap in front of the data is allowed to insert the record
insert image description here
Insertion Intention Gap Lock (insert intention lock)

A simple insert will add an exclusive lock on the index record corresponding to the inserted row. This is a record lock and there is no gap, so it will not block other sessions from inserting records in the gap.

However, before the insert operation, a lock will be added. The official document calls it an insertion intention gap lock, which is an intentional gap lock. The purpose of this intentional gap lock is to indicate that when multiple transactions are concurrently inserted into the same gap, as long as the inserted record is not in the same position in the gap, it can be completed without waiting for other sessions, so that the insert operation does not need to add real gap lock.

Insertion concurrency will be lower if Gap Lock is used

How to troubleshoot deadlocks?

conditions for deadlock

  1. Mutual exclusion, shared resources X and Y can only be occupied by one thread
  2. Occupy and wait, thread T1 has acquired shared resource X, and does not release shared resource X while waiting for shared resource Y
  3. No preemption, other threads cannot forcibly preempt the resources occupied by thread T1
  4. Circular waiting, thread T1 waits for the resources occupied by thread T2, and thread T2 waits for the resources occupied by thread T1, which is circular waiting

Let's create an example of deadlock first, and show you the basic troubleshooting ideas for deadlock.

CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单编号',
  `status` tinyint(3) NOT NULL COMMENT '订单状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='订单表';

insert into order_info (id, status) values (1, 0), (2, 0);
time Client A Client B
T1 begin;
update order_info set status = 1 where id = 1;
T2 begin;
update order_info set status = 2 where id = 2;
T3 update order_info set status = 1 where id = 2;
T4 update order_info set status = 2 where id = 1;
deadlock rollback
T1 commit;

When a deadlock occurs, mysql will choose a transaction with the least overhead to roll, so that another transaction can execute normally

Execute the following statement to get the latest deadlock record

show engine innodb status 

Please add image description
From the deadlock log, we can analyze the following useful information

The following statement is being executed when transaction 1 deadlocks

update order_info set status = 1 where id = 2;

The following statement is being executed when transaction 2 deadlocks

update order_info set status = 2 where id = 1;

And the lock waiting for transaction 1 is exactly the lock acquired by transaction 2, and it is certain that the lock waiting for transaction 2 has been acquired by transaction 1.

At this point, we need to look at the business code, how the deadlock is generated, as long as the conditions for the deadlock are destroyed.

For example, to avoid the deadlock in this example, we only need to destroy the condition of circular waiting and update the resources in order (that is, when updating multiple resources, they are updated according to the id from small to large)

The production environment is deadlocked

Let's talk about a deadlock problem we encountered in the production environment before, in order to deepen everyone's impression (of course, the actual situation is not so easy to troubleshoot, because there are many SQL executed in a transaction, so it is a test of skills to quickly find out the problem)

There are the following 2 tables, insert an account record

CREATE TABLE `balance_account` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '账户编号',
  `member_code` varchar(50) NOT NULL COMMENT '用户编号',
  `balance` bigint(20) NOT NULL COMMENT '账户余额',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='账户表';

CREATE TABLE `balance_charger` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `member_code` varchar(50) NOT NULL COMMENT '用户编号',
  `charger_num` varchar(50) NOT NULL COMMENT '流水单据号',
  `status` tinyint(3) NOT NULL COMMENT '流水状态,0初始状态,1完成',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1 COMMENT='账户流水表';

insert into balance_account(id, member_code, balance) value (1, 'a', 0);

When the money in the user account changes, we need to operate these two tables in sequence

// 插入流水
insert balance_charger;

// 更新账户
update balance_account;

// 更新流水
update balance_charger;
time Client A (Tab A) Client B (Tab B)
T1 begin;
insert into balance_charger (member_code, charger_num, `status`) values (‘a’, ‘v1’, 0);
update balance_account set balance = balance + 100 where id = 1;
T2 begin;
insert into balance_charger (member_code, charger_num, `status`) values (‘a’, ‘v2’, 0);
update balance_account set balance = balance + 100 where id = 1;
T3 update balance_charger set status = 1 where charger_num = ‘v1’;
T4 deadlock rollback
T5 commit;

How did this deadlock come about?
insert image description here
When the where condition of the update statement does not use an index, a full table scan will be performed, and Next-key Lock will be added to the records of the full table, which is equivalent to locking the entire table!

How to solve it?

Very simple, just add an index to the column in the where condition

ALTER TABLE balance_charger ADD INDEX idx_charger_num(`charger_num`) 

Reference blog

[1]https://mp.weixin.qq.com/s/B_slzAZLp-y8G0haZwIbTg
[2]https://bbs.huaweicloud.com/blogs/300169
插入意向锁
[3]https://www.cnblogs.com/better-farther-world2099/articles/14722850.html
[4]https://juejin.cn/post/6844903666856493064

Guess you like

Origin blog.csdn.net/zzti_erlie/article/details/123443999