我有一个名为spot
和reservation
的表格。 spot
包含列spot_id
和spot_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锁定。
我的问题是理论上的:
答案 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锁定行,然后只修改此行,则不会发生死锁。要发生死锁,您需要至少两个资源,这些资源是按不同顺序的事务获取的。