The principle of MySQL deadlock and how to locate and solve it?

What is a deadlock

Deadlock refers to the phenomenon of two or more transactions occupying each other on the same resource and requesting to lock the resources occupied by each other, which leads to a vicious circle. When multiple transactions try to lock resources in different orders, deadlocks may occur. When multiple transactions lock the same resource at the same time, deadlock will also occur. For example, imagine that the following two transactions process the StockPrice table at the same time:

Transaction 1

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 and date = '2002-05-02';
COMMIT;

Transaction 2

 START TRANSACTION;
UPDATE StockPrice SET high = 20.12 WHERE stock_id = 3 and date = '2002-05-02';
UPDATE StockPrice SET high = 47.20 WHERE stock_id = 4 and date = '2002-05-01';
COMMIT;

If it happens, both transactions executed the first UPDATE statement, updated a row of data, and also locked the row of data, and then each transaction tried to execute the second UPDATE statement, but found that the row has been locked by the other party , And then both transactions are waiting for the other to release the lock, and at the same time holding the lock that the other needs, it will fall into an endless loop. Unless external factors intervene, it is possible to remove the deadlock.

In order to solve this problem, the database system implements various deadlock detection and deadlock timeout mechanisms. The more complex the system, such as the InnoDB storage engine, the more it can detect the deadlock's circular dependency and return an error immediately. This solution is very effective, otherwise deadlock will lead to very slow queries. Another solution is to give up the lock request when the query time reaches the lock wait timeout setting. This method is usually not good. InnoDB's current method of dealing with deadlocks is to roll back the transaction that holds the fewest row-level exclusive locks (this is a relatively simple deadlock rollback algorithm).

The lock behavior and sequence are related to the storage engine. Execute the statements in the same order, some storage engines will deadlock, some will not. There are two reasons for deadlocks: some are due to real data conflicts, which are usually difficult to avoid, but some are entirely due to the implementation of the storage engine.

After the deadlock occurs, only a partial or complete rollback of one of the transactions can break the deadlock. For transactional systems, this is unavoidable, so applications must consider how to deal with deadlocks when designing. In most cases, you only need to re-execute the transaction that was rolled back due to deadlock.

How to avoid deadlock

  1. Similar business logic accesses tables and rows in a fixed order (basically it can solve most problems, such as transfers, all functional interfaces are to reduce money first and then add money)
  2. Large transactions are split into small ones, and large transactions are more inclined to deadlock. If business permits, split large transactions into small ones
  3. In the same transaction, try to lock all the resources needed at once to reduce the probability of deadlock
  4. Lower the isolation level. If the business permits, lowering the isolation level is also a better choice (a bit nonsense, but it also works.)
    5 Add a reasonable index to the table, you can see that if you don't take the index, it will record each row of the table. The locks obtained by adding locks (or table locks)
    without indexing transaction statements are all table locks. The higher the table lock level, the higher the probability of deadlock.

View deadlock log

Deadlock scenario:
transaction A operation select * from table where id =1 for update
transaction B operation select * from table where id = 2 for update
transaction A operation select * from table where id = 2 for update
transaction B operation select * from table where id =1 for update
is stuck at this time. Transaction A is waiting for transaction B to release the lock, and transaction B is waiting for transaction A to release the lock. The
solution is simple, just find the DBA to look at the deadlock log, and then according to the corresponding SQL, find the corresponding code and change it. The
show engine innodb status command can view the deadlock information

How to read MySQL's deadlock log

https://www.yuque.com/docs/share/016b2375-68b1-4ad8-92e8-62eb71b24792?# "How does MySQL read the deadlock log"

Detailed introduction of deadlock

https://www.yuque.com/docs/share/e437b034-6813-4171-be8b-712279d7865c?# "Remember an online SQL deadlock accident: How to avoid deadlock?

Guess you like

Origin blog.csdn.net/qq_41489540/article/details/113795080