Mysql - 并行事务中的行级锁定死锁

时间:2014-08-08 11:23:55

标签: php mysql transactions

我有一个名为spotreservation的表格。 spot包含列spot_idspot_status。对于预订过程,我启动一个事务,然后使用此查询获取特定行的锁定。我正在使用php和mysql。

//start transaction

SELECT * FROM spot WHERE spot_id = $id FOR UPDATE ;  
//if this query is successful then   

1. set spot status to 1
2. insert corresponding values in reservation table.  

and then commit else rollback           

//transactions ends

假设有2个并发事务T1和T2试图保留相同的点。根据我从本网站的其他问题和答案中学到的,如果交易不是并发的,那么就没有任何问题,但在并发操作中,处理器可以随时从T1的时间表改为T2。通过T1获取行锁后,让处理器切换到事务T2。 T2然后尝试获取同一行上的锁,但它不能被T1锁定。

我的问题是理论上的:

  1. mysql何时删除了锁?还是有任何明确的方式 自己移除锁?
  2. 由于T2事务无法锁定第一个查询的行,它是否会回滚?或者处理器是否保持T2等待它可以锁定行?
  3. 在这个问题中发生死锁的可能性有多大?

2 个答案:

答案 0 :(得分:0)

您的锁定管理策略是正确的。

如果T1首先获得spot / spot_id = $ id上的锁定,则T2将等待,直到T1提交或回滚事务。如果T1崩溃或超时,则回滚将是隐式的。

如果你想要死锁,试试这个。

获取T1锁定第1行(“fork”),然后第2行(“knife”)。 获取T2以锁定第2行(“刀”),然后锁定第1行(“叉”)。

同时运行它们。最终你会得到T2只拿一把刀,而T1只拿着一把叉子。他们会盯着对方,挨饿,每个人都在等着对方制定工具。

答案 1 :(得分:0)

当获得锁定的事务已结束并提交或回滚时,将删除锁定。在事务结束之前,mysql无法释放行级锁定,因为:

  

InnoDB以一种格式存储行锁,以便后来无法知道哪个锁是由哪个语句设置的

但是你可以使用user defined locks(又名顾问锁,也称为合作锁),可随时发布。

T2事务将等待直到获得锁定但不超过inno_lock_wait_timeout秒。在后一种情况下,将发生无法获取锁定的错误。

如果按id锁定行,然后只修改此行,则不会发生死锁。要发生死锁,您需要至少两个资源,这些资源是按不同顺序的事务获取的。

相关问题