MySQL'选择更新'行为

时间:2012-01-13 10:59:03

标签: mysql transactions locking

根据MySql文档,MySql支持多粒度锁定(MGL)。

情况下-1

打开终端-1:

//连接到mysql

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id, status from tracking_number limit 5 for update;
+----+--------+
| id | status |
+----+--------+
|  1 |      0 |
|  2 |      0 |
|  3 |      0 |
|  4 |      0 |
|  5 |      0 |
+----+--------+
5 rows in set (0.00 sec)
mysql> 

打开并打开终端2:

//连接到mysql

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select id, status from tracking_number limit 5 for update;

<!-- Hangs here. and after some time it says-->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

虽然有很多行需要检索,但T2会等到t1完成。

情况下-2

离开终端-1,现在在终端-2中:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

<!-- case 2.1 -->
mysql> select id, status from tracking_number where id=1;
+----+--------+
| id | status |
+----+--------+
|  1 |      0 |
+----+--------+
1 row in set (0.00 sec)

mysql> select id, status from tracking_number where id=2;
+----+--------+
| id | status |
+----+--------+
|  2 |      0 |
+----+--------+
1 row in set (0.00 sec)

<!-- case 2.2 -->
mysql> select * from tracking_number where id=2 for update;
<!-- Hangs here. and after some time -->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
  1. 但为什么在案例1中,T2会等待T1锁定的同一组行?

  2. 这是否意味着无限制的选择查询(即使使用limint参数。我尝试过不同的范围也会阻塞整个表格?

  3. 有没有办法让交易独立锁定而不指定记录的字段(即,不使用 where field = value )?
  4. 通常(或者根据Java并发锁定),写入锁定是独占的而读取不是。在案例2.1中,虽然记录处于写锁定模式,T2如何读取相同的记录?由于这是允许锁定它的重点是什么?
  5. 案例2.2被理解。
  6. 打开终端和交易:

    mysql> update tracking_number set status=4 where status=0 limit 5;
    Query OK, 5 rows affected (0.00 sec)
    Rows matched: 5  Changed: 5  Warnings: 0
    

    把它留在那里并打开另一个终端和交易:

    mysql> update tracking_number set status=5 where status=0 limit 5; 
    

    在我提交(或回滚)T1之前,T2没有成功。

    1. 为什么会出现这种情况?

1 个答案:

答案 0 :(得分:23)

让我来看看你的案例并解释这些锁是如何工作的:

1例

T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,并将X锁定放在前5行。

T2想要更新测试表中的某些行。此事务将IX(因为IX与IX兼容)锁定在所有表上并尝试前5行但由于X与X不兼容而无法执行此操作

所以我们没事。

2.1案例

T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,X锁定在前5行。

T2想要从测试表中选择一些行。并且它没有放置任何锁(因为InnoDB提供非锁定读取)

2.1案例

T1想要更新测试表中的某些行。此事务将IX锁定放在所有表上,X锁定在前5行。

T2想要更新(选择更新)测试表中的某些行。将IS放在整个表上并尝试对该行进行S锁定并失败,因为X和S不兼容。


还要始终注意隔离级别:不同级别会导致释放/获取锁定的机制不同

希望有所帮助