【问题标题】:PHP - Difference between all PDO transaction and stricly MySQL transaction?PHP - 所有 PDO 事务和严格的 MySQL 事务之间的区别?
【发布时间】:2014-08-30 16:36:12
【问题描述】:

我已经在网上搜索了大约 2 天,试图找出使用所有 PDO 或所有 MySQL 进行事务的差异和可能的优势/劣势。

我对每个成员进行大约 20 次插入,您可以同时注册多个成员,这样查询的数量就可以轻松地从 20 增加到 100 多个,我们对活动的估计范围可以从每小时发生的数百到数千次不等。

我了解事务,但我似乎不明白将所有插入批量放入一个 PDO 准备或将它们全部分开之间是否有很大区别。 示例:

$stmt1 = $pdo->prepare($query1);
$stmt2 = $pdo->prepare($query2);
$stmt3 = $pdo->prepare($query3);
$stmt4 = $pdo->prepare($query4);
....

$pdo->beginTransaction();

try{
  foreach($members as $member)
  {
    $stmt1->execute($member);
    $stmt2->execute($member);
    $stmt3->execute($member);
    $stmt4->execute($member);
    ....
  }
  $pdo->commit();
catch(Exception $e)
{
  $pdo->rollback();
}

对比一下:

//Inserts for ALL members
$sql = "
START TRANSACTION;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
INSERT INTO...;
COMMIT;";

try{
  $pdo->prepare($sql);
  $stmt->execute($member);

catch(Exception $e)
{
  $pdo->query("ROLLBACK;");
}

这是否会产生开销,因为必须一次发送一个查询,然后在 PHP 端继续解析,或者通过一个 PDO 调用一次发送所有查询是否有益?

更新

我注意到第二个示例中的混淆,我已对其进行了编辑。为清楚起见,该问题指的是使用多个 PHP 端查询(PDO 一次执行每个 SQL 语句,仍在一个事务中)与使用一个 PDO 执行(仍然只有一个事务)。

【问题讨论】:

  • 在您的第一个 sn-p 中,$pdo->beginTransaction()$pdo->commit(); 放错了位置。它们应该都在循环内部或都在循环之外。我想你的问题是他们什么时候在循环之外?如果两者都在里面,那么你的两个方法是严格等价的。
  • 你说得对,我匆匆完成了这个例子。无论如何,这不是直接代码。我对这两种可能的方法之间的差异更感兴趣。

标签: php mysql sql pdo transactions


【解决方案1】:

您是使用 PDO API 还是使用本机 (My)SQL 语句有些无关紧要。性能差异将接近于零,因为 PDO 只是在一天结束时发出 SQL 语句的抽象类*。换句话说:

$pdo->beginTransaction();
$stmt1->execute($query1);
$stmt2->execute($query2);
$pdo->commit();

... 真的是一样的:

$stmt1->execute('START TRANSACTION;' . $query1 . $query2 . 'COMMIT;');

您真正关心的是在一个单独的事务中创建每个成员,还是在一个全局事务中创建所有成员更好。大多数情况下,在一个事务中插入所有内容会更快。

【讨论】:

  • 我想我明白你在说什么。这更像是我的一位同事的不安全感。如果使用 beginTransaction() 与另一个基本相同,那么这就回答了我的问题。如果 PDO 对象发送请求、返回、发送另一个请求等等,则更多的关注是问题;速度变慢,因为您在每次查询时都在从应用程序到数据库进行通信。
  • 我在第二个示例中意识到了一些轻微的混淆,插入语句将包括所有成员,最后只有一个提交。
【解决方案2】:

当我阅读PDO documentation on transactions 时,这两种方法是等效的。也就是说,PDO 将使用驱动程序级别的事务功能,在 pdo_mysql 的情况下,应该启动本机 MySQL 事务。

我认为要考虑的更大问题正是您想要实现的目标。您是出于性能原因使用事务,还是因为数据是相关的,如果一条语句失败则不应插入任何内容?

如果是前者,我建议对其进行基准测试。如果是后者,您需要构造代码,使逻辑相关的数据在同一个事务中。


根据问题更新进行编辑:

我倾向于说发出一个大的 SQL 语句会更快,因为应该有更少的网络流量开销(假设 Web 和数据库服务器不在同一台主机上)。有了“好的”硬件和正确的应用程序配置配置,MySQL 应该能够每秒处理数千次插入。

当然,在不了解您的设置细节的情况下,这纯粹是猜测。但我怀疑这种应用程序级别的优化远不如调优数据库服务器有效。

唯一确定的方法是对两种方式进行基准测试,看看其中一种是否明显优于另一种。

【讨论】:

  • 我在完整性意义上使用事务,而如果一个失败,则不应添加任何内容。感谢您的洞察力。
  • 我在第二个示例中意识到了一些轻微的混淆,插入语句将包括所有成员,最后只有一个提交。
  • 感谢您对更新的回复,非常感谢。我发现了一个类似的问题(stackoverflow.com/questions/10863598/…),答案和你的一样; “过早的优化”。
猜你喜欢
  • 2011-09-23
  • 1970-01-01
  • 2018-02-07
  • 2013-03-25
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 2012-04-26
  • 2015-11-15
相关资源
最近更新 更多