- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
当两个任务试图选择
然后插入
同一个表时发生死锁。过程如下:
Task_1 Task_2
------ ------
Phase 1 | SELECT SELECT
Phase 2 | INSERT INSERT
SELECT count(id) from mytbl where name = 'someValue' and timestampdiff(hour, ts, now()) < 1;
INSERT mytbl (id, name, ts) values ('newId', 'anotherValue', now());
死锁日志如下(删减了一些细节):
------------------------
LATEST DETECTED DEADLOCK
------------------------
151225 8:22:17
*** (1) TRANSACTION:
TRANSACTION 0 746402, ACTIVE 0 sec, process no 4690, OS thread id 140411390486272 inserting
mysql tables in use 1, locked 1
LOCK WAIT 1172 lock struct(s), heap size 112624, 32914 row lock(s)
MySQL thread id 3909, query id 31751474 10.20.36.38 mydb update
INSERT INTO mytbl -- truncated
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 5044 n bits 88 index `PRIMARY` of table `MYDB`.`mytbl` trx id 0 746402 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) TRANSACTION:
TRANSACTION 0 746449, ACTIVE 0 sec, process no 4690, OS thread id 140411389953792 inserting, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
1172 lock struct(s), heap size 112624, 32914 row lock(s)
MySQL thread id 3906, query id 31751477 10.20.36.38 mydb update
INSERT INTO mytbl -- truncated
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 5044 n bits 88 index `PRIMARY` of table `MYDB`.`MYTBL` trx id 0 746449 lock mode S
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 5044 n bits 88 index `PRIMARY` of table `MYDB`.`MYTBL` trx id 0 746449 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** WE ROLL BACK TRANSACTION (2)
SELECT
语句使用不需要S 锁 的快照读取。 INSERT
语句需要对要插入的单行进行 X 锁定。那为什么Task_2
持有S锁导致死锁呢?SHOW CREATE TABLE
的结果如下:
| task_content | CREATE TABLE `mytbl` (
`id` bigint(20) NOT NULL,
`ts` timestamp NULL DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
最佳答案
文章here对锁和隔离级别进行了详尽的解释。
感谢@newtover 提供有关隔离级别的线索。我对这篇文章的总结和我自己的问题的答案如下:
InnoDB 中默认的隔离级别是Repeatable Read,它会锁定索引(不锁定数据表)直到事务结束。
在我的情况下,唯一的索引是 PRIMARY
,它在我的 SELECT
查询中没有用(可以通过 explain select...
验证) >).结果,PRIMARY
索引中的所有 条目都被锁定。当 TXN_2
等待某个条目上的 X 锁 时,该条目被 TXN_1
保留的 S 锁 锁定>。同样,TXN_1
等待另一个条目上的 X 锁,但该条目也被自身保留的 S 锁 锁定。 "one S two X"发生死锁。
相比之下,在 name
列上创建索引 name
后,索引 name
将在 SELECT 中使用
语句(可以通过 explain select ...
验证),因此锁将在索引 name
而不是 PRIMARY
。更重要的是,SELECT
语句只会对等于 someValue
的条目发出 S 锁,而不是索引 name
。此外,
INSERT
所需的IX 锁 和X 锁 将在索引PRIMARY
上发出。 S锁与IX锁、X锁的冲突将得到解决。
列
name
上的索引不仅加快了查询速度,更重要的是防止锁定索引的所有条目。
关于并发 INSERT 和 SELECT 导致的 MySQL 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34448539/
我有类似下面的代码: ... id: myComponent signal updateState() property variant modelList: [] Repeater { mo
我正在处理一些我无法展示的私有(private)代码,但我已经制作了一些示例代码来描述我的问题: 主.c: #include #include #include #include typede
这个问题在这里已经有了答案: 关闭10 年前。 Possible Duplicate: what are the differences in die() and exit() in PHP? 我想
在编写 Perl 模块时,在模块内部使用 croak/die 是一个好习惯吗? 毕竟,如果调用者不使用 eval block ,模块可能会使调用它的程序崩溃。 在这些情况下,最佳做法是什么? 最佳答案
我有一些搜索线程正在存储结果。我知道当线程启动时,JVM native 代码会代理在操作系统上创建新 native 线程的请求。这需要 JVM 之外的一些内存。当线程终止并且我保留对它的引用并将其用作
我刚刚花了很多时间调试一个我追溯到 wantarray() 的问题。 .我已将其提炼为这个测试用例。 (忽略 $! 在这种情况下不会有任何有用信息的事实)。我想知道为什么wantarray在第二个示例
我看到一些代码是这样做的: if(something){ echo 'exit from program'; die; } ...more code 和其他只使用 die 的人: if
我正在尝试将此表格用于: 如果任何 $_POST 变量等于任何其他 $_POST 变量抛出错误。 如果只有几个,那不是问题,但我有大约 20 个左右所以如果我想这样做,我将不得不像这样 但这
每次我运行: hadoop dfsadmin -report 我得到以下输出: Configured Capacity: 0 (0 KB) Present Capacity: 0 (0 KB) DFS
我是一名优秀的程序员,十分优秀!