Mysql one minute positioning Next-Key Lock, you take a few minutes

One minute positioning Next-Key Lock, you take a few minutes

Tags: Mysql, Next-KeyLock, insert intent lock

Connecting thread

Viewing Connection Information show processlist

+----+------+------------------+------+---------+------+----------+------------------+
| Id | User | Host             | db   | Command | Time | State    | Info             |
+----+------+------------------+------+---------+------+----------+------------------+
| 3  | root | 172.17.0.1:60542 | test | Query   | 0    | starting | show processlist |
| 5  | root | 172.17.0.1:60546 | test | Sleep   | 4168 |          | <null>           |
| 8  | root | 172.17.0.1:60552 | test | Sleep   | 4170 |          | <null>           |
+----+------+------------------+------+---------+------+----------+------------------+

mysql non-enterprise version supports only a link to a thread

View threading model show variables like 'thread_handling'

+-----------------------------------------+---------------------------+
| Variable_name                           | Value                     |
+-----------------------------------------+---------------------------+
| thread_handling                         | one-thread-per-connection |
+-----------------------------------------+---------------------------+

[Transaction commit strategy]
has two hidden transaction commit time point to note, the first one is autocommit=1 Mysql session -level variables automatically submit all ORM transaction commit control are subject to the influence of this field in the framework of the current sentence will automatically be submitted by default but if it is displayed begin transaction open their own affairs require manual submission. Sometimes ORM framework will be based on some settings or strategy, autocommit is set to 0.

The second is that the former DDL operations will implicitly commit the current transaction, some mixed DML and DDL scripts used together, so there will be consistency. DDL automatically commits the current transaction. Because DDL prior to 5.7 do not support the principle of operation of the transaction. (Mysql8.0 already supports transactional DDL)

Next-Key Lock investigation

Next-Key Lock occurs only in RR (REPEATABLE-READ) under isolation level.

Mysql There are many types of species of locks, 表锁, , record lock, gap lock, 意向共享/排他锁, 插入意向锁, 元数据锁, Auto_Incr自增锁excluded metadata lock , Auto_Incr increment lock after the rest of the lock combination is the next most RR isolation level.

RR isolation level is the default transaction isolation level, is one of the strengths of Mysql, under the RR isolation level transaction maximum throughput, and will not appear phantom read problem. Next-Key Lock is to solve this problem, it simply record lock + gap lock is the Next-Key Lock .

_ Read _ Magic fundamental problem is found at the boundaries of recorded value, such as the number of 30-year-old older than our statistics: select count(1) peoples where age>30This statement is likely to get for each query result set is not the same, because they meet the age> 30 's record into our peoples in the table will be hit query.

So, we need to solve the phantom read not only does not allow recording gap is inserted into the record, but also to prevent the record has been modified twice, before and after the two records as if it has been modified interval becomes large, there will be a phantom read occurs.

We look at an example.

 CREATE TABLE `peoples` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_peoples_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4
+----+-----+
| id | age |
+----+-----+
| 1  | 20  |
| 2  | 30  |
| 3  | 35  |
| 4  | 40  |
+----+-----+

To facilitate debugging, innodb will acquire a lock timeout transfer large point

show variables like '%innodb_lock_wait%'
set innodb_lock_wait_timeout=600

Open two sessions.

session A id=8:
begin
select count(1) from peoples where age>30 for update;
session B id=5:
begin
insert into peoples(age) values(31)

show processlist Id find connections.

***************************[ 1. row ]***************************
Id      | 3
User    | root
Host    | 172.17.0.1:60542
db      | test
Command | Query
Time    | 0
State   | starting
Info    | show processlist
***************************[ 2. row ]***************************
Id      | 5
User    | root
Host    | 172.17.0.1:60546
db      | test
Command | Query
Time    | 394
State   | update
Info    | insert into peoples(age) values(31)
***************************[ 3. row ]***************************
Id      | 8
User    | root
Host    | 172.17.0.1:60552
db      | test
Command | Sleep
Time    | 396
State   |
Info    | <null>
  • Affairs

select * from information_schema.innodb_trx \G Check the implementation of the transaction.

***************************[ 1. row ]***************************
trx_id                     | 457240
trx_state                  | LOCK WAIT
trx_started                | 2020-01-27 06:08:12
trx_requested_lock_id      | 457240:131:4:4
trx_wait_started           | 2020-01-27 06:09:25
trx_weight                 | 6
trx_mysql_thread_id        | 5
trx_query                  | insert into peoples(age) values(31)
trx_operation_state        | inserting
trx_tables_in_use          | 1
trx_tables_locked          | 1
trx_lock_structs           | 5
trx_lock_memory_bytes      | 1136
trx_rows_locked            | 4
trx_rows_modified          | 1
trx_concurrency_tickets    | 0
trx_isolation_level        | REPEATABLE READ
trx_unique_checks          | 1
trx_foreign_key_checks     | 1
trx_last_foreign_key_error | <null>
trx_adaptive_hash_latched  | 0
trx_adaptive_hash_timeout  | 0
trx_is_read_only           | 0
trx_autocommit_non_locking | 0
***************************[ 2. row ]***************************
trx_id                     | 457239
trx_state                  | RUNNING
trx_started                | 2020-01-27 06:07:59
trx_requested_lock_id      | <null>
trx_wait_started           | <null>
trx_weight                 | 3
trx_mysql_thread_id        | 8
trx_query                  | <null>
trx_operation_state        | <null>
trx_tables_in_use          | 0
trx_tables_locked          | 1
trx_lock_structs           | 3
trx_lock_memory_bytes      | 1136
trx_rows_locked            | 5
trx_rows_modified          | 0
trx_concurrency_tickets    | 0
trx_isolation_level        | REPEATABLE READ
trx_unique_checks          | 1
trx_foreign_key_checks     | 1
trx_last_foreign_key_error | <null>
trx_adaptive_hash_latched  | 0
trx_adaptive_hash_timeout  | 0
trx_is_read_only           | 0
trx_autocommit_non_locking | 0

457,240 transaction state is LOCK WAITwaiting for the lock, 457,239 state of affairs is RUNNINGexecution, we are waiting for the transaction commits.

  • lock

select * from information_schema.innodb_locks \G View occupancy lock.

***************************[ 1. row ]***************************
lock_id     | 457240:131:4:4
lock_trx_id | 457240
lock_mode   | X,GAP
lock_type   | RECORD
lock_table  | `test`.`peoples`
lock_index  | idx_peoples_age
lock_space  | 131
lock_page   | 4
lock_rec    | 4
lock_data   | 35, 7
***************************[ 2. row ]***************************
lock_id     | 457239:131:4:4
lock_trx_id | 457239
lock_mode   | X
lock_type   | RECORD
lock_table  | `test`.`peoples`
lock_index  | idx_peoples_age
lock_space  | 131
lock_page   | 4
lock_rec    | 4
lock_data   | 35, 7

innodb_locks table contains the information already acquired the lock request and lock information. lock_index field indicates a lock to go index, record locks are based indexing is complete.

The state of the transaction is above 457,240 to acquire the lock lock_data | 35, 7, the requested data representation. The transaction is currently occupied by 457,239 X lock.

  • Lock Wait

select * from information_schema.innodb_lock_waits Check the lock wait information.

***************************[ 1. row ]***************************
requesting_trx_id | 457240
requested_lock_id | 457240:131:4:4
blocking_trx_id   | 457239
blocking_lock_id  | 457239:131:4:4

457,240 transactions need to get 131: 4: 4 lock, occupied 131 457 239 Services: 4: 4 lock.

  • innodb Monitor
    show engine innodb status
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 422032240994144, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 457240, ACTIVE 394 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 7 row lock(s), undo log entries 1
MySQL thread id 5, OS thread handle 140556966967040, query id 105 172.17.0.1 root update
insert into peoples(age) values(31)
------- TRX HAS BEEN WAITING 165 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 131 page no 4 n bits 72 index idx_peoples_age of table `test`.`peoples` trx id 457240 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000023; asc    #;;
 1: len 4; hex 00000007; asc     ;;

------------------
---TRANSACTION 457239, ACTIVE 407 sec
3 lock struct(s), heap size 1136, 5 row lock(s)
MySQL thread id 8, OS thread handle 140556966696704, query id 104 172.17.0.1 root

MySQL thread id 5 is being prepared on the insert intent locks, 插入意向锁essentially lock plus a gap, in order to ensure maximum concurrent inserts, irrelevant rows into not being mutually exclusive. thread id 5 plus the need to ensure that the gap before inserting lock, the main problem is consistency brought prevent concurrent inserts.

session 5, and session 8 are not operating to id = 3, age = 35 record, but was X + Gap Lock locked, the only way to solve the problem of phantom read.

Author: Wang Qingpei (Fun headlines Tech Leader)

Guess you like

Origin www.cnblogs.com/wangiqngpei557/p/12236155.html