Mysql concurrency in mind a "deadlock", the problem leads and discussion

These days, when viewing the article, found a Mysql concurrency problems, just by virtue of the eye to see, did not find problems and solutions at the outset, so we carry concrete and practical test:

(I want to learn programming from a small partner search circle T community , more and more industry-related industry information about free video tutorials. Oh, absolutely free!)

First, the problem

Within a transaction: insert the records based on field p to update this record, but when there is concurrent operations, will update at the dead lock problem occurs, the update changed id, all right.

Same table, high concurrent transactions, the transaction to insert a record, then update this record:
(1) if the update is a unique index, abnormal;
(2) if the update is to increment the primary key, no abnormality;
voiceover : Do not be "dead lock" describing the confusion, deadlock is blocking problems, or other abnormalities, yet another said.

Second, test and reproduce the problem

2.1 Data Preparation

create table t (id int(20) primary key AUTO_INCREMENT,cell varchar(20) unique)engine=innodb;

New table: (1) storage engine innodb, MySQL version 5.6; (2) id field increment primary key; (3) cell field, a unique index;

start transaction;
insert into t(cell) values(11111111111);
insert into t(cell) values(22222222222);
insert into t(cell) values(33333333333);
commit;

Insert some test data.

2.2 session parameters

Set the transaction isolation level RR (repeatable read)

--设置手动提交
--设置事务隔离级别为RR
set session autocommit=0;
set session transaction isolation level repeatable read;

2.3 simulate concurrent

A plurality of terminals simulate concurrent session transaction
Here Insert Picture Description

start TRANSACTION;
INSERT INTO t(cell) VALUES(44444444);
UPDATE t set cell = 123 WHERE cell = 44444444 ;
ROLLBACK;
start TRANSACTION;
INSERT INTO t(cell) VALUES(5555555);
UPDATE t set cell= 456 WHERE cell = 5555555 ;
ROLLBACK;

Open two windows in Navicat

  1. Window A, first start a transaction, and insert records;
  2. Window B, then starting the transaction record is also inserted;
  3. Window A, modify the record inserted;
  4. Window B, modify the inserted record;

2.4 results

Strange appeared!
  • When you run the update transaction 1, there have been waiting for!
  • When you run the update 2 transaction, a deadlock occurred, automatic rollback

Third, inquiries

Logically, insert the records do not conflict, then modify this record, line lock should not conflict ah? The only index, primary key index of how it will be different? Whether related? Is a deadlock, or other reasons?

3.1 According to show engine innodb status inquiry

Puzzled, then take a look at what it has in innodb status after copying and pasting down View:
Here Insert Picture Description

Transaction1 Transaction2 visible and locked at the same time the same part, but locak_mode X rec bur not gap Record lock

This is very strange, but not lock deadlock caused by the gap, the first update Why wait for it, why would a deadlock second update it?

Do not, then look at another place

3.2 Table View innodb_locks

Here Insert Picture Description

By looking at information_schema library inndb_locks table, you can see, indeed Transaction 1 and Transaction 2 while locked up a data area, resulting data wait, deadlock, but the problem then?

So for ways to view again:

3.3 explain / desc sql statement

Here Insert Picture Description

what! We found a major problem
why there is actually 6 rows!
Why do I update will sweep the whole table? ?
I added the index ah

Found the problem: Update index did not go, but sweep the whole table!

Fourth, to solve the problem

Since the problem is found, take a look at how to solve, why not take the index update it?
Then we go back and look at two update statements

UPDATE t set cell = 123 WHERE cell = 44444444 ;
UPDATE t set cell= 456 WHERE cell = 5555555 ;

I saw that it was nothing problem that way?

Seeking to find tired tired, desolate, desolately sad, and finally, when viewing the table, found the problem:

Looking back construction of the table statement / Table Structure

create table t (id int(20) primary key AUTO_INCREMENT,cell varchar(20) unique)engine=innodb;

cell field data type is varchar type, and we write the update is cell = 444444;

Not the data quoted! Which led to the update did not take the index, a full table scan

So, we'll look at this process from the beginning:

In the transaction isolation level RR (Repeat Read) the
insert 1 produces a transaction intent lock insert, insert transaction 2 also had an insert intent lock (not locked to each other, because the data lines are not in conflict)
at this time transaction 1 then update statement for failing to take the index, resulting in a full table scan, and in the sweeping piece of data to the transaction 2 is inserted, and insert intent row lock lock conflicts, resulting in the need to wait for the transaction transaction 1 2 intention to release the lock and insert wait.
2 during the update transaction, also need to scan the whole table, but full table update transactions are locked 1, 2 transactions need to wait 2 wait for the transaction to release the lock insert intent transaction row lock release 1, so that the occurrence of the dead lock

That solution is very simple, the statement read:

UPDATE t set cell = 123 WHERE cell = "44444444" ;
UPDATE t set cell= 456 WHERE cell = "5555555" ;

To resolve the deadlock / wait issue

Fifth, the extension of the problem

RR comparison with the 5.1 RC

5.1.1 table contains historical data test

In fact, during testing, has also been doubted is not because of the RR, RC try to change it?

--将事务隔离级别改为RC
SET TRANSACTION ISOLATION LEVEL REPEATABLE COMMITTED;

After the modification, it performs the same operation:
Here Insert Picture Description
found: Transaction 1insert, 2insert, transaction 1 transaction update to take effect, the transaction occurred waiting for update 2

According to the above problems we find, analyze:

  • 1 during the update transaction, but also a full table scan, but because there is no gap RC lock, there is no intent lock insert, update and therefore will not be waiting for transaction 1
  • 2 during the update transaction, the transaction need to wait for update submitted 1 releases the lock, and therefore the occurrence of waiting

came to a conclusion:

The absence of a gap lock RC

Table 5.1.2 does not contain historical data tests (table is empty)

For comparison of RC and RR, we took a method to delete the data on the data in the table continue testing:

truncate table 

Continued operation of the same table, the results:

  • Under RR affairs is still waiting for 1, 2 transaction deadlock
  • RC is lower transaction 1 and transaction 2 are normal, it did not occur to wait

The reason, under RR, 1 insert transaction data, transaction 2 can be seen, so in RR, even if the data is cleared, still locked transaction transaction 1 2 inserted.
And in the RC, insert data transaction transaction 1 2 see transaction data transaction 1 2 inserted can not see, they just locked up their own data inserted, it can execute successfully.

5.1.3 Conclusion

Despite repeatable read and read what they have been submitted several times to read can be read out in the same transaction, but the discovery of their other differences:

  • RC key is not present in the gap, the gap belonging to the same intent lock inserted into the lock does not exist
  • Under RR, insert data transaction transaction 1 2 can be seen, RC transactional data transactions 2 1 Insert see

5.2 Mysql lock insertion gap intent lock

In this process, we found: row locks, lock gap, insert intent lock. And by the different behavior of different locks, and its significance, usefulness is different:

5.2.1 Lock gap (Gap Locks)
  1. Lock interval, only a lock index section (opening section, do not include double endpoint).
  2. In the gap between the index record locking, either before or after a lock record an index, the index does not include the record itself. In example 2, 3, the lock may have the value of the gap (∞, 1), (1, 2), (2, ∞).
  3. It may be used to prevent gaps phantom read lock, to ensure that the data will not be inserted between the index
5.2.2 insert intent lock (Insert Intention Locks)
  1. Gap insert intent lock is a lock, the lock is not the intent, generated when operating insert.
  2. When data is written to a different space while the same index in multiple transactions, and does not need to wait for other transactions to complete, lock wait will not happen.
  3. Suppose there is a record index contains key values ​​4 and 7, are inserted into different transaction. 5 and 6, and every transaction is generated between a plus 4-7 intention lock insertion, acquire an exclusive lock on the inserted line, but They will not be locked to each other, because the data lines are not in conflict.
  4. Insert intent locks do not block any lock for the inserted record will hold a record lock.

5.2.3 Lock option

When we deal with sql statement to execute a different statement will choose different locks:

  • If the update condition is not taking the index, such as the implementation of "update test set name =" hello "where name =" world ";", this time will be a full table scan, scan the table when you want to block any other update operations, so the rise table lock.

  • If the update condition is index field, but not the only index (including primary key index), such as performing "update test set name =" hello "where code = 9;" then the time will be updated using the Next-Key Lock. Use of the reasons Next-Key Lock:

  1. First, to ensure compliance with the conditions on record plus exclusive lock, it will lock the current non-unique index value and the corresponding primary key index;

  2. But also to ensure the lock interval can not insert new data.

  3. If the condition is a unique index update, use the Record Lock (recording lock).

Guess you like

Origin blog.csdn.net/wanghao112956/article/details/93467091