【问题标题】:PDO+mysql -> random deadlocks that require a connection resetPDO+mysql -> 需要重置连接的随机死锁
【发布时间】:2018-07-11 07:53:27
【问题描述】:

对不起,很长的文字,我认为我在 mysql 数据库或 PDO/mysqli 内部遇到了一个错误,并尝试尽可能好地解释这种情况。 我故意没有发布代码,在那种情况下它不相关。

我有一个非常繁忙的 mysql 服务器,平均每秒查询 1000 个,每天大约有 100 万个连接。

我运行 mysql 5.5.42 和 php 5.6.33
我希望我可以升级,但它是一个生产环境,我不想在更新期间冒风险。

我使用 Innodb 作为数据库引擎(50GB 内存用于缓冲区)

现在我的问题是我有随机、可重复的死锁,没有并发查询,也没有使用事务。
它会影响几个表和脚本。

在 INSERT 和 UPDATE 期间发生死锁。
我已经缩小了一些位置,从 mysql 理论来看,在任何情况下都不会出现死锁。
不使用事务,在 WHERE 子句中的单个(主)ID 上进行简单的 INSERT 或 UPDATE。
我了解死锁是如何发生的,而且我遇到死锁的情况都没有风险。

我已对该问题进行了调试,因为它有时会导致我的脚本完全停止。
我尝试在死锁之后进行 sleep() 并再次插入/更新,但是我可以这样做一千次,但它不会工作,它会永久死锁。
如果我在新的 mysql 会话之外同时执行此操作,则查询有效!

解决此问题的唯一方法是检测死锁,关闭 PDO 连接 ($pdo = null;),重新连接到数据库并重复查询。

虽然这可行,但必须在任何地方引入这种逻辑是相当痛苦的。

我一直在浏览互联网,但找不到与我提到的问题类似的任何内容。所有的死锁通常都是正确的,原因可以理解。

第二个相关问题: 这个比较少见,但似乎相关,它是 INSERT 上的错误 DUPLICATE KEY 错误。它发生在百万分之一的插入中,因此非常罕见。 但在这些情况下,只有 PDO 重新连接才能解决问题。

我很想得到一些意见,也许有人理解这个问题,或者在没有像重新连接这样的黑客攻击的情况下解决了这个问题。

总结:根本没有使用事务(默认自动提交),没有并发查询,innodb 正在使用,简单的单个 INSERT 查询或 WHERE id=1234 的 UPDATE; 死锁只会影响随机行。

这似乎是 mysql 数据库内部的一个错误,可能是会话损坏。

这里的死锁日志: 第一个表也确实有一个死锁问题,每小时一次。 我可以将其追溯到一些非常简单的 UPDATE 查询,这些查询每小时进行一次,它们大约需要 0.05 秒才能完成。 另一个错误日志有数百个条目,没有进一步的细节。

    RECORD LOCKS space id 1983 page no 32800 n bits 1616 index start of table `db`.`jobs` trx id 2083002285 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;
Record lock, heap no 859 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259d6; asc   Y ;;

Record lock, heap no 860 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259d7; asc   Y ;;

Record lock, heap no 861 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259d8; asc   Y ;;

Record lock, heap no 862 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259d9; asc   Y ;;

Record lock, heap no 863 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259da; asc   Y ;;

Record lock, heap no 864 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259db; asc   Y ;;

Record lock, heap no 865 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259dc; asc   Y ;;

Record lock, heap no 866 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259dd; asc   Y ;;

Record lock, heap no 867 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259de; asc   Y ;;

Record lock, heap no 868 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 1; hex 81; asc  ;;
 1: len 4; hex 800259df; asc   Y ;;

Innodb 状态:

InnoDB 
=====================================
2018-02-07 17:21:27 0x7f5b0d32d700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 22 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 64463 srv_active, 0 srv_shutdown, 21 srv_idle
srv_master_thread log flush and writes: 64472
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 2040099
OS WAIT ARRAY INFO: signal count 3213946
RW-shared spins 0, rounds 2165320, OS waits 554744
RW-excl spins 0, rounds 40616534, OS waits 873123
RW-sx spins 532360, rounds 9261545, OS waits 97422
Spin rounds per wait: 2165320.00 RW-shared, 40616534.00 RW-excl, 17.40 RW-sx
------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-02-07 17:15:05 0x7f5af7924700
*** (1) TRANSACTION:
TRANSACTION 2109880254, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 147614, OS thread handle 140029031933696, query id 36166552 localhost website Searching rows for update
UPDATE task SET result_delivered=1, result_data='DISABLED', result_gathered=1 WHERE result_data is NULL AND (assigned_counter >= 4 OR other_counter> 1)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 591 page no 20571555 n bits 88 index PRIMARY of table `db`.`task` trx id 2109880254 lock_mode X locks rec but not gap waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 24; compact format; info bits 0
 0: len 4; hex 8611338d; asc 3 ;;
 1: len 6; hex 00007dc237bc; asc } 7 ;;
 2: len 7; hex 3300070012073a; asc 3 :;;
 3: len 4; hex 800085dc; asc ;;
 4: len 30; hex 226973742064617320776569c39f652042726175746b6c656964206e6963; asc "ist das wei e nic; (total 46 bytes);
 5: len 7; hex 44656661756c74; asc Default;;
 6: len 2; hex 656e; asc en;;
 7: len 0; hex ; asc ;;
 8: len 2; hex 8032; asc 2;;
 9: len 1; hex b2; asc ;;
 10: len 2; hex 8001; asc ;;
 11: len 4; hex 80030ea7; asc ;;
 12: len 19; hex 692d3036626437323830373833326335656230; asc i-06bd72807832c5eb0;;
 13: SQL NULL;
 14: len 30; hex 7b22636f756e745f6f7267616e6963223a31332c22636f756e745f637265; asc {"count_organic":13,"count_cre; (total 5060 bytes);
 15: len 4; hex 5a7b3419; asc Z{4 ;;
 16: len 1; hex 81; asc ;;
 17: len 1; hex 80; asc ;;
 18: len 1; hex 80; asc ;;
 19: len 3; hex 80000d; asc ;;
 20: len 3; hex 800000; asc ;;
 21: len 1; hex 80; asc ;;
 22: len 1; hex 81; asc ;;
 23: len 1; hex 80; asc ;;

*** (2) TRANSACTION:
TRANSACTION 2109880252, ACTIVE 0 sec updating or deleting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 146705, OS thread handle 140028677342976, query id 36166547 localhost ss updating
UPDATE task SET result_count_creative='0'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 591 page no 20571555 n bits 88 index PRIMARY of table `db`.`task` trx id 2109880252 lock_mode X locks rec but not gap
Record lock, heap no 5 PHYSICAL RECORD: n_fields 24; compact format; info bits 0
 0: len 4; hex 8611338d; asc 3 ;;
 1: len 6; hex 00007dc237bc; asc } 7 ;;
 2: len 7; hex 3300070012073a; asc 3 :;;
 3: len 4; hex 800085dc; asc ;;
 4: len 30; hex 226973742064617320776569c39f652042726175746b6c656964206e6963; asc "ist das wei e nic; (total 46 bytes);
 5: len 7; hex 44656661756c74; asc Default;;
 6: len 2; hex 656e; asc en;;
 7: len 0; hex ; asc ;;
 8: len 2; hex 8032; asc 2;;
 9: len 1; hex b2; asc ;;
 10: len 2; hex 8001; asc ;;
 11: len 4; hex 80030ea7; asc ;;
 12: len 19; hex 692d3036626437323830373833326335656230; asc i-06bd72807832c5eb0;;
 13: SQL NULL;
 14: len 30; hex 7b22636f756e745f6f7267616e6963223a31332c22636f756e745f637265; asc {"count_organic":13,"count_cre; (total 5060 bytes);
 15: len 4; hex 5a7b3419; asc Z{4 ;;
 16: len 1; hex 81; asc ;;
 17: len 1; hex 80; asc ;;
 18: len 1; hex 80; asc ;;\

【问题讨论】:

  • 动态设置全局 innodb_print_all_deadlocks=1;请花几个小时并发布生成的error.log。记住下班后,SET GLOBAL innodb_print_all_deadlocks=0;如果合适的话。
  • @WilsonHauck 我会将问题中的内容作为更新发布
  • 感谢更新,这是 2 小时的 error.log 吗?我们还需要 SHOW ENGINE INNODB STATUS; ,请完整 my.cnf/ini。
  • @WilsonHauck 这只是一小部分,还有很多,主要是那些“物理”部分。我正在更新我的 q 中的状态。该查询“UPDATE task SET result_delivered=1, result_data='DISABLED', result_gathered=1 WHERE result_data is NULL AND (assigned_counter >= 4 OR other_counter> 1)”是导致死锁的查询之一。它们每分钟都是由 crontab 制作的。我已经对其进行了测试,它只需要几分之一秒即可完成。
  • 似乎只发布了 SHOW ENGINE INNODB STATUS 的一部分。现在,请发布 A) SHOW CREATE TABLE 任务的完整结果; B:SHOW INDEX FROM 任务;用于分析可用索引。我认为您在欧洲是因为时间差异。

标签: php mysql pdo deadlock


【解决方案1】:

更新任务 SET result_count_creative='0'

您有机会为 result_count_creative 添加到表索引并将您的查询更改为:

更新任务 SET result_count_creative='0' WHERE result_count_creative > '0'

EXPLAIN EXTENDED SELECT SQL_NO_CACHE .....应该显示第一次更新时使用的扫描,第二次更新时没有扫描。将避免许多行锁。
显示警告;

会立即在会话中向您展示优化器如何重新排列查询。

这只会减少部分死锁。还需要昨天申请的 SCT 和 SHIF,请有空。

【讨论】:

    猜你喜欢
    • 2013-09-28
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多