【问题标题】:Please help me understanding MySQL InnoDB Transactions请帮助我理解 MySQL InnoDB 事务
【发布时间】:2013-05-06 19:26:36
【问题描述】:

我正在尝试了解 InnoDB 的锁定机制。

假设我有以下 PHP 脚本:

mysql_query('BEGIN;');
$a=mysql_query('SELECT id, status FROM testtable WHERE id=123 LIMIT 1 FOR UPDATE;'); 
$res=mysql_fetch_assoc($a);
$b=somefunction($res['id']);
$c=someotherfunction($b);
mysql_query('UPDATE testtable SET status=1 WHERE id=123;');
mysql_query('COMMIT;');

在 somefunction() 和 someotherfunction() 中,我们将从同一个表中执行许多其他查询,但也来自其他表。它甚至从 id=123 的 testtable 中选择其他字段。

我是否理解正确,在这个会话中我可以使用 id=123 做任何我想做的事情,但其他会话将等待锁定被释放?

因为我在第一个查询中使用了“for update”,所以这是 testtable 中唯一会被锁定的行。在同一会话中选择/更新/插入的任何其他表或行都保持不变(解锁)?

如果 someotherfunction() 选择并更新 id=123 上的不同字段会发生什么?这可能吗?锁会保留吗?

【问题讨论】:

    标签: php mysql locking innodb commit


    【解决方案1】:

    我不确定锁定部分,但进行事务以允许对一组查询进行“全有或全无”。

    例如,如果您要针对某种付款运行以下两个查询:

    UPDATE customer SET credit=credit - 1 WHERE id=1;
    INSERT INTO subscriptions VALUES (...);
    

    例如,如果 INSERT 查询失败,客户的信用额度将减少,但不会获得订阅。

    通过将其包装在事务中,如果查询的任何部分失败,它就会恢复到以前的状态。

    BEGIN;
    UPDATE customer SET credit=credit - 1 WHERE id=1;
    INSERT INTO subscriptions VALUES (...);
    COMMIT;
    

    要么两个查询都成功,要么失败时不做任何更改。

    编辑:我不相信 InnoDB 会自动为您进行任何锁定,请查看 SELECT ... LOCK IN SHARE MODESELECT ... FOR UPDATE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多