Web*_*eng 18 php mysql pdo transactions
在PHP文件说:
如果您以前从未遇到过交易,它们提供了4个主要功能:原子性,一致性,隔离和耐用性(ACID).通俗地说,任何在交易中进行的工作,即使是分阶段进行的,也可以保证安全地应用于数据库,并且在承诺时不受其他连接的干扰.
题:
这是否意味着我可以有两个单独的PHP脚本同时运行事务而不会相互干扰?
通过 " 干扰 "来实现我的意思:
想象一下,我们有下employees表:
__________________________
| id | name | salary |
|------+--------+----------|
| 1 | ana | 10000 |
|------+--------+----------|
Run Code Online (Sandbox Code Playgroud)
如果我有两个具有相似/相同代码的脚本,并且它们在同一时间运行:
script1.php和script2.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;//increasing salary
$stmt = $conn->prepare("UPDATE employees SET salary = {$salary} WHERE name = ?");
$stmt->execute(['ana']);
$conn->commit();
Run Code Online (Sandbox Code Playgroud)
并假设事件序列如下:
script1.php选择数据
script2.php选择数据
script1.php更新数据
script2.php更新数据
script1.php commit()发生了
script2.php commit()发生了
在这种情况下,ana的薪水是多少?
它会是11000吗?那么这是否意味着1个事务将与另一个事务重叠,因为信息是在提交之前获得的?
它会是12000吗?那么这是否意味着无论数据更新和选择的顺序如何,该commit()功能都会强制这些单独发生?
请随意详细说明事务和单独脚本如何相互干扰(或不干扰).
根据给定的条件(一个单独的DML语句)判断,这里不需要事务,而是表锁.这是一个非常普遍的混乱.
如果您需要确保所有DML语句都已正确执行或根本未执行,则需要进行事务处理.
手段
虽然,正如Shadow中的优秀答案所指出的那样,你可以在这里使用具有适当隔离级别的事务,但这会相当混乱.你需要的是表锁定.InnoDB引擎允许您锁定特定行而不是锁定整个表,因此应该是首选.
如果你想要薪水是1200 - 然后使用表锁.
或者 - 更简单的方法 - 只需运行原子更新查询:
UPDATE employees SET salary = salary + 1000 WHERE name = ?
Run Code Online (Sandbox Code Playgroud)
在这种情况下,将记录所有工资.
如果您的目标不同,请更好地明确表达.
但同样重要的是:你必须明白,事务通常与单独的脚本执行无关.关于竞争条件的主题,您不了解交易,而是对表/行锁定感兴趣.这是一个非常常见的混淆,你最好直接学习它:
事务和锁定干扰的唯一主题是死锁,但同样 - 只有在事务使用锁定时才会出现这种情况.
唉,“无干扰”需要程序员的一些帮助。它需要BEGIN并COMMIT定义“交易”的范围。和...
你的例子是不够的。第一个语句需要SELECT ... FOR UPDATE. 这告诉事务处理很可能会UPDATE出现获取的行SELECT。该警告对于“防止干扰”至关重要。现在时间线是这样的:
FOR UPDATE)(注意:这不是“死锁”,只是“等待”。)
| 归档时间: |
|
| 查看次数: |
1461 次 |
| 最近记录: |