我是不是需要事务才能按顺序获得正确的最后插入 ID?
Posted
技术标签:
【中文标题】我是不是需要事务才能按顺序获得正确的最后插入 ID?【英文标题】:Do i need transactions to get the correct last inserted ID in a sequence?我是否需要事务才能按顺序获得正确的最后插入 ID? 【发布时间】:2018-09-21 23:40:48 【问题描述】:我有一个名为 products 的数据库表,我试图在表中插入产品 A,并在产品 A 插入表后返回产品 A 的 ID。我的 php 代码如下:
public function save(Product $product) : int
$stmt = $this->conn->prepare(
"INSERT INTO products VALUES(null, ?, ?, ?, ?)"
);
$error = ! $stmt->execute([
$product->name,
$product->description,
$product->picturePath,
$product->userId,
]);
return $error ? -1 : $this->conn->lastInsertId('products.id');
我正在考虑使用此代码可能遇到的问题,我想到的第一个问题是:如果客户请求将产品 A 插入表中,并且在我获得产品 A 的 ID 之前,另一个请求插入产品B,我会得到产品B的ID吗?是的?如果没有,为什么不呢?
第二个问题是:如果我使用事务插入产品A并检索它的id,那么我会得到产品A的id吗?
【问题讨论】:
【参考方案1】:您可以用try
和catch
包围它,并使用PDO begintransaction、commit 和rollback 函数。例子可以在PHP PDO:lastinsertId详细说明
try
$conn->beginTransaction();
$stmt = conn->prepare(
"INSERT INTO products VALUES(null, ?, ?, ?, ?)"
);
$error = ! $stmt->execute([
$product->name,
$product->description,
$product->picturePath,
$product->userId,
]);
$id = $conn->lastInsertId();
$conn->commit();
catch(PDOExecption $e)
$conn->rollback();
print "Error!: " . $e->getMessage() . "</br>";
IMO 最好采用良好的编码实践,而不是一时兴起并希望获得最好的结果。 :)
【讨论】:
我同意在事务中进行所有数据库操作,它确实有助于确保您的数据库处于干净状态。【参考方案2】:我认为你应该没问题,因为在 mysql 中它与连接绑定,并且该请求应该使用相同的连接。其他请求可能同时发生,递增表中的最高 ID,但不应返回这些值。
MySQL docs 中解释得很好
对于 LAST_INSERT_ID(),最近生成的 ID 保存在 服务器基于每个连接。它不会被另一个人改变 客户。
【讨论】:
谢谢,php代码和mysql服务器之间的连接是如何工作的对我来说很有趣,我会尝试更多地了解它。【参考方案3】:lastInsertId()
值是每个连接维护的,因此如果有其他连接将数据插入到同一个表中,您不必担心这些;您的价值将是您连接的价值。
如果您使用成功的事务然后回滚,lastInsertId()
仍将保留其值。回滚不会影响lastInsertId()
的当前值。
【讨论】:
谢谢,您是否也从 mysql 文档中获得了这些信息? 其实我试了一下,发现rollback并没有改变值。 好的。我认为这应该是另一个问题:PDOStatement::execute 文档说,如果发生某些故障,将返回 false,但是在 lastInsertedId 文档中,没有提到任何值,以防互联网连接中断等故障,我想我会使用 try /catch 仅用于处理 lastInsertedId 失败,我不会使用任何事务。以上是关于我是不是需要事务才能按顺序获得正确的最后插入 ID?的主要内容,如果未能解决你的问题,请参考以下文章