我已经知道当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
是一个虚拟表,它对事务进行求和以获得用户的余额。
当有合理数量的用户使其难以测试时,通常会注意到此错误,有关如何避免死锁或任何可能的解决方案的任何提示,因为我以非常多的方式将行插入事务表中并查找解决它!
我也尝试过捕获异常,但我无法创建一个循环来重做查询,直到它完成。
答案 0 :(得分:0)
只有当您拥有两个或更多资源,两个或更多进程,并且进程以不同顺序锁定资源时,才会发生死锁。
说,进程1想要锁定资源A,然后是B,然后是C.进程2想要锁定B,然后是A,然后是C。
如果1获得A,则可能导致死锁,然后2获得B,然后1等待B,2等待A - 无限期。
谢天谢地,解决方案非常简单:如果进程需要锁定两个或多个资源,它必须在" sorted"时尚。在这个例子中, 如果进程2也得到A,那么B,然后是C,死锁永远不会发生。
我的情况是,您似乎在一个事务中以或多或少的随机顺序锁定不同的表行。尝试找出如何使用mysql释放锁定,并确保您只持有实际需要的数量。如果您需要一次保留多个,请尝试以某种方式订购您的请求。
在不了解更多关于您的代码的情况下很难说出来......第一次谷歌攻击" mysql死锁"虽然显示了一些有前途的东西:https://www.percona.com/blog/2014/10/28/how-to-deal-with-mysql-deadlocks
答案 1 :(得分:0)
我创建了一个包含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)
现在我选择行并计算ID为+10。你看他必须阅读所有行
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)