[英]mysql innodb table lock - when update one line block update on another line
当在MySQL(innodb)中创建死锁时,以“ 高性能MySQL ”的第10页为例。 但是,如果我在一个事务中更新测试的一行,则更新另一行将被阻止并最终超时。 就像innodb在更新where条件时使用表级别锁而不是行级别锁一样。 这种情况与innodb的行级别锁不符。
Mysql版本:
mysql> status
--------------
mysql Ver 14.14 Distrib 5.6.26, for Linux (x86_64) using EditLine wrapper
Connection id: 2
Current database: test
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.6.26 MySQL Community Server (GPL)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 4 hours 52 min 1 sec
Threads: 3 Questions: 107 Slow queries: 0 Opens: 69 Flush tables: 1 Open tables: 62 Queries per second avg: 0.006
--------------
mysql> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
创建测试表:
mysql> show create table t\G;
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`a1` int(11) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL,
`c` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> select * from t;
+------+------+------+
| a1 | b | c |
+------+------+------+
| 1 | a | b |
| 2 | aa | bb |
+------+------+------+
2 rows in set (0.00 sec)
然后打开两个独立的会话以创建两个事务
第一场
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update t set b='x' where a1=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
在会话2中,更新将被阻止,最终超时
mysql> start transaction
-> ;
Query OK, 0 rows affected (0.00 sec)
mysql> update t set c='yy' where a1=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
在阻止期间,使用InnoDB插件获取锁定关系
mysql> SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread,
-> r.trx_query waiting_query,
-> b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
-> b.trx_query blocking_query
-> FROM information_schema.innodb_lock_waits w
-> INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
-> INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
+----------------+----------------+--------------------------------+-----------------+-----------------+----------------+
| waiting_trx_id | waiting_thread | waiting_query | blocking_trx_id | blocking_thread | blocking_query |
+----------------+----------------+--------------------------------+-----------------+-----------------+----------------+
| 5933 | 6 | update t set c='yy' where a1=1 | 5932 | 5 | NULL |
+----------------+----------------+--------------------------------+-----------------+-----------------+----------------+
1 row in set (0.00 sec)
原则上,会话1中的行锁不会阻止会话2中的更新。
如果遇到这样的问题,请您帮忙解释一下为什么会话2被阻止。
不要考虑在没有PRIMARY KEY
InnoDB中使用事务。
并在执行UPDATE ... WHERE ai = constant
时认真考虑至少使用INDEX(a1)
。
否则,InnoDB的“行级别锁定”会变得很草率-可能是因为难以在不建立索引的情况下抓住每个“行”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.