为什么使用SELECT FOR UPDATE?

ozxc1zmp  于 2022-10-03  发布在  Mysql
关注(0)|答案(2)|浏览(287)

我有一个关于我们使用SELECT FOR UDPATE的目的的问题?它到底是做什么的?

我有2个表,我需要从表中选择行,并更新相同的行。

例如:

选择查询

SELECT * from  t1 WHERE city_id=2 for update

更新查询

UPDATE t1 SET final_balance = final_balance - 100 WHERE city_id ='2'

我的问题是,这是否真的锁定了读取操作,直到我的更新完成,或者它到底处理了什么?

我的想法是,在我的更新完成之前,没有人可以读取/更新这些行。

sc4hvdpw

sc4hvdpw1#

SELECT ... FOR UPDATE将使用写(排他)锁锁定记录,直到事务完成(提交或回滚)。

要选择记录并确保在更新之前不对其进行修改,您可以启动一个事务,使用SELECT ... FOR UPDATE选择该记录,执行一些快速处理,更新该记录,然后提交(或回滚)该事务。

如果在事务之外使用SELECT ... FOR UPDATE(自动提交打开),则锁仍将立即释放,因此请确保使用事务来保留锁。

为了提高性能,不要让事务打开很长时间,因此应该立即进行更新。

bwntbbo3

bwntbbo32#

MySQL中,SELECT FOR UPDATE用于防止更新丢失。*在MySQL中,只有SERIALIZABLE才能防止丢失更新而不使用SELECT FOR UPDATE,但在SERIALIZABLE中出现了死锁,所以我们应该使用SELECT FOR UPDATE,即使是SERIALIZABLE

  • 丢失更新**是指两个事务读取同一行进行更新,但第一个提交的更新被第二个提交的更新覆盖。

接下来,在MySQL上,我会先向您展示更新丢失,然后是选择更新,如何防止更新丢失

例如,有**“产品”表**,包含**“id”“名称”“股票”**,如下所示。*当客户购买产品时,产品库存减少:
Id|名称|股票
-|-|

1|苹果|10
2|橙色|20

首先,下面这些步骤不使用SELECT FOR UPDATEMySQL上显示UPDATE丢失

Flow|Transaction 1(T1)|Transaction 2(T2)|说明
-|-|

第一步|BEGIN;||T1启动。
第二步||BEGIN;|T2启动。
第三步|SELECT stock FROM product WHERE id = 2;20||t1读20,后因客户购买7个橙子,更新为13。
Step 4||SELECT stock FROM product WHERE id = 2;20|t2读20,因为客户买了4个橘子,所以更新为16。
Step 5|UPDATE product SET stock = '13' WHERE id = 2;||t1将20更新为13。
Step 6|COMMIT;||t1提交。
Step 7||UPDATE product SET stock = '16' WHERE id = 2;|T2在T1提交后将13更新为16。
Step 8||COMMIT;|t2提交,#*更新丢失

其次,下面这些步骤展示了如何在MySQL上使用SELECT FOR UPDATE防止更新丢失

Flow|Transaction 1(T1)|Transaction 2(T2)|说明
-|-|

第一步|BEGIN;||T1启动。
第二步||BEGIN;|T2启动。
Step 3|SELECT stock FROM product WHERE id = 2 FOR UPDATE;20||当选择更新时,T1读为20,后续更新为13,因为客户购买了7个橘子。
Step 4||SELECT stock FROM product WHERE id = 2 FOR UPDATE;|t2需要等待t1提交读取stock,并带有SELECT FOR UPDATE。
Step 5|UPDATE product SET stock = '13' WHERE id = 2;|正在等待...|T1将20更新为13。
第六步|COMMIT;|正在等待...|T1提交。
Step 7||SELECT stock FROM product WHERE id = 2 FOR UPDATE;13|现在加上SELECT FOR UPDATE,T2的读数是13,因为客户买了4个橘子,所以以后会更新为9。
Step 8||UPDATE product SET stock = '9' WHERE id = 2;|T2在T1提交后将13更新为9。
步骤9||COMMIT;|t2提交,#*不丢失更新

相关问题