繁体   English   中英

mysql innodb table lock-更新一条线时更新另一条线

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM