php - 这是Mysql的Bug吗? 关于SELECT ... FOR UPDATE lock_mode X 插入意图
问题描述
有一个表结构是 id,aid,......aid 是一个索引(一种 int 类型)
trx1 and 2: begin;
trx1: select max(id) from a where aid = 10 for update;
trx2: select max(id) from a where aid = 10 for update; ## have blocked waiting trx 1
trx1: insert into a (........; then trx 2 will throw a deadlock even not commit yet
这个错误不能在 PHP 中抛出,在 PHP 和 MySQL 中没有错误。just-auto rollback 然后继续执行其他代码。
更改以下 MySQL 查询顺序:
trx1 and 2: begin;
trx1: select max(id) ... for update;
trx1: insert ...;
trx2: select max(id) ... for update;
trx1: commit; the trx2 result is currectly
我的 MySql 版本是 5.7 我被看到(同类型的问题):在 MySQL 中插入意向锁的解决方案
和这个:https ://bugs.mysql.com/bug.php?id=25847
对于下面的测试代码:
//prepared:
CREATE TABLE `test_lock` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`aid` int(11) NOT NULL,
`otherinfo` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `aid` (`aid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
insert into `test_lock` (`aid`) values(10);
##trx1 and trx2
begin;
##trx1
select max(id) from `test_lock` where (`aid` = 10) limit 1 for update;
##trx2(have blocked)
select max(id) from `test_lock` where (`aid` = 10) limit 1 for update;
##trx1
insert into `test_lock` (`aid`) values(10);
##then trx2 will gave a deadlock error and look that error
show engine innodb status\G;
使用 PHP 进行测试(我使用 Laravel5.6 命令):
//file1:
$aid = 10;
DB::beginTransaction();
$result = DB::table('test_lock')->where('aid', $aid)->orderByDesc('id')->lockForUpdate()->first();
var_dump($result);
echo "after get:" . date('Y-m-d H:m:s.u'). "\r\n";
sleep(10); // wrong
DB::table('test_lock')->insert(
['aid' => $aid]
);
echo "after insert:" . date('Y-m-d H:m:s.u'). "\r\n";
//sleep(10); // correctly and file2 is correct result
DB::commit();
//file2
$aid = 10;
DB::beginTransaction();
$pdo = DB::connection()->getPdo();
$result = DB::table('test_lock')->where('aid', $aid)->orderByDesc('id')->lockForUpdate()->first();
var_dump($result); //NULL
echo "after get:" . date('Y-m-d H:m:s.u'). "\r\n";
var_dump($pdo->errorCode()); // 00000
$ret = DB::table('test_lock')->insert(
['aid' => $aid]
);
echo "after insert:" . date('Y-m-d H:m:s.u'). "\r\n";
DB::commit();
在 PHP File2 结果为 NULL。没有任何错误抛出。没有 mysql 错误日志。你可以使用 show engine innodb status\G; 发现僵局发生了。
有什么办法可以给我帮助吗?
解决方案
推荐阅读
- python - simple-salesforce 中的 Salesforce MFA
- php - XAMPP 服务器已被 CORS 策略阻止:
- java - Apache camel Blueprint 在 Blueprint Container 启动期间有未解决的依赖组件=https
- java - 消费者不读取来自 Kafka 主题的消息(Akka Stream Kafka)
- r - R根据其他列有条件地添加指定数量的新行
- javascript - 从机器人所在的服务器获取服务器所有者
- python - 了解python递归函数
- python - 为数组中的元素创建等级
- apache-spark - Spark 执行器突然停止向配置的 JMX 接收器报告监控指标
- sql - SQL 更新 WHERE IN 子查询已停止工作