mysql - InnoDB 选择更新

标签 mysql pdo innodb

如果我有一个 InnoDB 表的简单语句

UPDATE <table> SET locked=1, col2=<Val2> WHERE locked=0

是否真的需要执行 SELECT FOR UPDATE?

由于 InnoDB 支持行级锁定,即使成千上万的客户端同时执行相同的脚本,是否有可能发生冲突?

更新:

像这样可以防止锁

$dbh = new PDO(DSN, DB_USER, DB_PASS);
$dbh->beginTransaction();
$selQuery = $dbh->prepare("SELECT <col> FROM <table> WHERE status=0 LIMIT 1 FOR UPDATE");
$selQuery->bindColumn(<col1>, $col1);
$selQuery->execute();

$selQuery->fetch(PDO::FETCH_BOUND);

$dbh->query("UPDATE <table> SET status=1 WHERE status=0 LIMIT 1");

$dbh->commit();

最佳答案

是的,碰撞总是会发生。所以使用设计模式:

SELECT FOR UPDATE 首先为给定事务中的所有资源,可以防止或缩短死锁情况。

假设以下场景:

  • 进程 A 按 1,2 的顺序更新表 1 和 2
  • 进程 B 按照 2,1 的顺序更新表 1 和 2

现在进程 A 更新表 1,同时进程 B 更新表 2,导致死锁(假设此更新命中了相同的“记录/页面”)。

但是,如果在事务开始时使用 SELECT FOR UPDATE,事务将在开始时阻塞,因为表 2(或表 1,无论哪个更快)无法锁定(还) .这里的关键部分是“在交易开始时”,如果您稍后再做,那么只需运行 UPDATE 就同样有效。

关键始终是保持事务的原子性和快速性:对 SQL 逻辑进行分组,以便它可以使用最少数量的其他代码执行,并尽可能缩短锁定时间。

关于mysql - InnoDB 选择更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43530086/

相关文章:

php - 如何通过PDO正确获取以表的主键作为数组键的数组?

MySQL #1452 - 无法添加或更新子行

mysql - hasMany 关系的查询可能很复杂;这可以做到吗?

mysql - 无法添加或更新子行 : a foreign key constraint fails?

c# - Linq 查询从 Sql 数据库返回重复记录

javascript - 下拉选择后显示表单以编辑表中的 mysql 数据

php - 在保持相同连接的同时在同一类中使用不同的 mysql 用户?

php - 使用 PDO 搜索

mysql - 没有 InnoDB 的 Magento

php - MySQL 表 - 如何在十亿行表上快速插入?