我知道,当sql查询试图锁定已经锁定的行时,就会发生死锁,而我目前遇到了死锁。下面是我的sql查询:
INSERT INTO transactions (product_id, category, C, amount, date) SELECT 'SomeProduct', 'SomeCategory', v.username, 10, '2016-3-31' FROM balance v WHERE v.username = 'SomeUsername' AND v.balance + 10 >= 0
balance是一个虚拟表,用于对交易进行求和以获得用户余额。
当有相当数量的用户时,这个错误通常会被注意到,这使得测试变得困难,任何关于如何避免死锁的提示或任何可能的解决方案,因为我正在以非常多的方式将行插入transaction表中,并希望解决它!
我也尝试过捕捉异常,但我不能创建一个循环来重做查询,直到它完成。
发布于 2016-04-01 05:03:14
一般答案
只有当您有两个或更多资源、两个或更多进程,并且这些进程以不同的顺序锁定资源时,才会发生死锁。
假设进程1想要锁定资源A,然后是B,然后是C。进程2想要锁定B,然后是A,然后是C。
这可能会导致死锁,如果1得到A,然后2得到B,然后1等待B,2无限期地等待A。
谢天谢地,解决方案非常简单:任何时候,如果一个进程需要锁定两个或更多资源,它必须以“排序”的方式进行锁定。在本例中,如果进程2也获得A,然后是B,然后是C,则永远不会发生死锁。
具体答案
在您的情况下,您似乎以或多或少的随机顺序锁定了一个事务中的不同表行。尝试找出如何使用mysql释放锁,并确保您只持有实际需要的锁。如果您需要同时保存多个请求,请尝试以某种方式对您的请求进行排序。
如果不对你的代码有更多的了解就很难断定...谷歌对"mysql deadlock“的第一次点击显示了一些有希望的东西:https://www.percona.com/blog/2014/10/28/how-to-deal-with-mysql-deadlocks
发布于 2016-04-01 05:34:56
我已经创建了一个包含2个字段的示例表。id有主键
MariaDB [who]> DESC mynum;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| num | float | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)我填满了100000条记录
MariaDB [who]> SELECT * FROM mynum LIMIT 10;
+----+----------+
| id | num |
+----+----------+
| 1 | 0.47083 |
| 2 | 0.670773 |
| 3 | 0.941373 |
| 4 | 0.69455 |
| 5 | 0.648627 |
| 6 | 0.159488 |
| 7 | 0.851557 |
| 8 | 0.779321 |
| 9 | 0.341933 |
| 10 | 0.371704 |
+----+----------+
10 rows in set (0.00 sec)
MariaDB [who]> SELECT count(*) FROM mynum;
+----------+
| count(*) |
+----------+
| 100000 |
+----------+
1 row in set (0.02 sec)现在我选择row并计算+10到id。您可以看到,他必须读取所有行
MariaDB [who]> EXPLAIN SELECT * FROM mynum WHERE id +10 > 20;
+------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | mynum | ALL | NULL | NULL | NULL | NULL | 100464 | Using where |
+------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)现在我将id与一个常量进行比较。您可以看到仅读取他们使用的行和使用索引
MariaDB [who]> EXPLAIN SELECT * FROM mynum WHERE id < 10;
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | mynum | range | PRIMARY | PRIMARY | 4 | NULL | 9 | Using where |
+------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)https://stackoverflow.com/questions/36343488
复制相似问题