从MySQL InnoDB存储过程锁定表以进行插入

时间:2017-01-15 11:52:46

标签: mysql stored-procedures concurrency innodb

我正在编写存储过程。在其中我有以下mysql插入语句:

INSERT INTO `Address`(`countryCode`, `addressLine1`, `addressLine2`, `postcode`, `region`, `city`) VALUES (country, addressLine1, addressLine2, postcode, region, city);
INSERT INTO `UserAddress`(`username`, `creationDate`, `addressId`) VALUES (username,NOW(),(SELECT addressId FROM Address ORDER BY addressId DESC LIMIT 1));

如您所见,我正在Address表上执行插入,然后在下一行的子查询中使用自动递增的“addressId”。现在,如果在这两个语句之间另一个事务会在Address表中插入一些东西,我会将错误的addressId插入UserAddress表中。我的猜测是我需要在执行这些语句时锁定Address表。

经过长时间的搜索,我找到了以下代码来锁定地址表:

SELECT addressId FROM Address FOR UPDATE;

这对新插入的行也有用吗?如果没有,那会是什么?

2 个答案:

答案 0 :(得分:1)

理想情况下,您应该在Transaction内使用' START TRANSACTION;'和' COMMIT'句法。您还需要将autocommit设置为0(默认情况下已启用)。 Here是交易和自动提交的文档。

只要您的更新包含在交易中并且设置了适当的isolation level,其他交易所做的更改就不会影响您的交易。

答案 1 :(得分:1)

这正是他们发明LAST_INSERT_ID

的原因
INSERT INTO `Address`(`countryCode`, `addressLine1`, `addressLine2`, `postcode`, `region`, `city`) VALUES (country, addressLine1, addressLine2, postcode, region, city);
INSERT INTO `UserAddress`(`username`, `creationDate`, `addressId`) VALUES (username,NOW(),LAST_INSERT_ID());

无需锁定或事务甚至存储过程来获取最后一个id。只需在您的应用中执行此操作。