插入和更新时的Mysql死锁

标签 mysql

我在中高负载情况下遇到了死锁。这是详细信息。

MySQL-5.5.21-55

引擎:InnoDB

表:顺序

# Field, Type, Null, Key, Default, Extra
id, bigint(20) unsigned, NO, PRI, , auto_increment
sno, varchar(32), NO, MUL, ,
misc1, int, NO, , 0,

表:订单项

# Field, Type, Null, Key, Default, Extra
id, bigint(20) unsigned, NO, PRI, , auto_increment
order_id, bigint(20), YES, MUL, , 
f1, varchar(50), YES, , , 
f2, varchar(100), YES, , , 
misc2, int, NO, , 0,
  • 顺序.sno是唯一的
  • OrderItem.order_id 未定义为外键,但在应用程序中用作外键
  • OrderOrderItem
  • 具有一对多关系
  • OrderItem.order_id + OrderItem.f1 + OrderItem.f2 是唯一的

用例:

  • 每当需要更新 OrderOrderItem 中的任何记录时,我想使旧记录失效(或删除)并插入新记录。
  • 可能发生的情况是,早些时候,Order 中的一条记录(例如 order1)在 OrderItem 中有 3 条记录(例如 orderItem1、orderItem2、orderItem3)。但现在我想将其设置为 order1->orderItem1、orderItem4、orderItem5 或全新的集合。这就是为什么我想使所有旧记录一起失效并插入新记录的原因,因为找出 OrderItem 中更改的内容很复杂。

多个线程会做这个操作;但他们将在不同的记录集上工作。我一次处理 25 个Order

我尝试了什么:

  • 插入订单;在重复键更新 Order 并从 OrderItem 中删除所有子项并插入 OrderItem s。
  • Order 中有另一个名为 is_active 的列,并将相同 sno 的所有记录标记为 0,并将新记录插入 >订单;将新的 child 插入到 OrderItem
  • 从给定 sno 的 Order 中删除;从 OrderItem 中删除相同的 sno。重新插入到两个表中。

上述所有方法有时都会导致死锁。 没有其他线程或进程正在处理这些表。

观察:

通过以下链接

并发现更新/删除多条记录会导致 MySQL 在 REPEATABLE_READ 隔离级别(默认)获得 Next Key 锁。在我看来,这会导致问题。

如果您能提供一些解决此问题的指导,我们将不胜感激。

最佳答案

既然你没有提到它,我试试看,你试过“FOR UPDATE”了吗?

将连接自动提交设置为 false。

在程序开始时,使用它来锁定所有相关数据。

SELECT o.* , oi.* 
FROM order o 
INNER JOIN orderitem oi ON (o.id=oi.order_id) 
WHERE o.id = <order id to update> 
FOR UPDATE;

然后你可以对这些条目做任何你想做的事情。 然后提交。

编辑:我认为问题的根本原因是多线程(很明显),我在想从等式中删除该元素是否更好。

想象一个系统,您有多个接收请求的接收器。这些接收器只会做类似的事情:

//select to check if there is a existing record(no need to lock), if no, return fail as response
SELECT o.* , oi.* 
FROM order o 
INNER JOIN orderitem oi ON (o.id=oi.order_id) 
WHERE o.sno = <sno to update>;

insert into request_buffer (request_id, sno, new_order_item,create_date .......) 
values
(1, abc , orderitem1......);
//return success after inserting buffer.

您有一个单独的单线程程序来汇集此表并处理这些缓冲区条目。

在那种情况下,它将多线程元素与数据库更新过程分开。我不确定传入请求的数量,但我认为如果您在每个周期/查询中处理更多请求,那么性能不会有太大不同吗?

关于插入和更新时的Mysql死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24819851/

相关文章:

mysql - 我想获得访问量最大的 5 个部分 desc 订购

javascript - 使用 CodeIgniter 中的复选框生成特定行的 Excel 报告

php - 如何通过 php 将这些数据从 mysql 插入到我的网页中?

sql - mysql CREATE VIEW 不能从 mysql_query 工作

MySQL:命令行与 phpMyAdmin

javascript - 在javascript中读取sql查询输出

mysql - gocraft/dbr : How to JOIN with multiple conditions?

php - 选择框中选择的不同值和 id

MySQL:从使用同一表的先前查询的结果中删除

php - 一起显示当天的事件(PHP/MYSQL)