首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >处理和防止死锁的正确方法

处理和防止死锁的正确方法
EN

Stack Overflow用户
提问于 2016-04-01 04:48:32
回答 2查看 1.1K关注 0票数 1

我知道,当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表中,并希望解决它!

我也尝试过捕捉异常,但我不能创建一个循环来重做查询,直到它完成。

EN

回答 2

Stack Overflow用户

发布于 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

票数 3
EN

Stack Overflow用户

发布于 2016-04-01 05:34:56

我已经创建了一个包含2个字段的示例表。id有主键

代码语言:javascript
复制
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条记录

代码语言:javascript
复制
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。您可以看到,他必须读取所有行

代码语言:javascript
复制
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与一个常量进行比较。您可以看到仅读取他们使用的行和使用索引

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36343488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档