数据库事务的话题经常伴随着缩写词 ACID,代表原子性、一致性、隔离性和持久性。简单来说,事务保证数据库操作可靠地执行,并且不受其他并发连接的影响。
但是,一个问题出现了:多个 PHP 脚本可以同时运行事务而互不干扰吗?要理解这一点,请考虑以下场景:
假设一个名为“employees”的表具有两个字段:“id”和“salary”。两个脚本 script1.php 和 script2.php 同时执行以下代码:
<code class="php">$conn->beginTransaction(); $stmt = $conn->prepare("SELECT * FROM employees WHERE name = ?"); $stmt->execute(['ana']); $row = $stmt->fetch(PDO::FETCH_ASSOC); $salary = $row['salary']; $salary = $salary + 1000; $stmt = $conn->prepare("UPDATE employees SET salary = {$salary} WHERE name = ?"); $stmt->execute(['ana']); $conn->commit();</code>
在这种情况下“ana”的最终工资是多少?
答案取决于为 MySQL InnoDB 表引擎配置的隔离级别。 InnoDB 支持 SQL 标准指定的四种隔离级别:
默认情况下,MySQL 使用“已提交读”隔离级别。在此级别中,结果将是 11000。这是因为 script1.php 和 script2.php 在提交之前读取相同的数据。
如果使用“可序列化”隔离级别,结果将为 12000。这是因为 Serialized 可确保事务按顺序执行并防止其他事务干扰锁定的数据。
在给定的示例中,事件顺序为:
通过“读取已提交”隔离,两个脚本在提交之前都会读取相同的数据。因此,工资的增加不是孤立的,而是应用了两次,导致增加了 2000。
通过“Serialized”隔离,第一个事务 (script1.php) 锁定“ana”的行,当它选择数据。当 script2.php 尝试选择相同的数据时,它将等到第一个事务提交。这样可以保证数据在读取时不会被其他事务修改,并且工资的增加只应用一次,结果增加了 1000。
因此,同时事务之间的干扰取决于隔离级别和具体的操作顺序。了解不同隔离级别的含义对于确保事务在并发环境中按预期运行至关重要。
以上是MySQL 事务与 PDO 可以并发运行而不会发生干扰吗?的详细内容。更多信息请关注PHP中文网其他相关文章!