锁定表时MySQL交换列:我的方法理论上无僵局吗?
我有一个朋友关系表,如下所示:
CREATE TABLE `FriendRelation` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id1` bigint(20) unsigned NOT NULL,
`user_id2` bigint(20) unsigned NOT NULL,
`is_both_way` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY (`user_id1`, `user_id2`),
) ENGINE=InnoDB;
朋友关系就像Twitter一样,一个人可以以单向方式关注另一个用户。只有当两个用户互相关注时,他们才能交换私人消息。旨在插入数百万行。
在我的预期用法中,当爱丽丝跟随鲍勃时,将使用user_id1 =爱丽丝的ID
,user_id2 = bob的ID
和is_both_way = 0
。当鲍勃返回is_both_way
标志设置为1时。
现在,如果爱丽丝(Alice)取消关注鲍勃(Bob is_both_way
标志回到0。
基本上我有两个过程psudocodes
function follow(self, target) {
begin transaction;
if ("select * from FriendRelation where user_id1=self and user_id2=target" is not empty) {
do nothing;
} elseif ("select * from FriendRelation where user_id1=target and user_id2=self for update" is not empty) {
"update FriendRelation set is_both_way=1 where user_id1=target and user_id2=self";
} else {
"insert into FriendRelation (user_id1, user_id2, is_both_way) values (self, target, 0)";
}
commit;
}
function unfollow(self, target) {
begin transaction;
if ("select * from FriendRelation where user_id1=self and user_id2=target for update" is not empty) {
"update FriendRelation set is_both_way=0, user_id1=target, user_id2=self where user_id1=self and user_id2=target";
} elseif ("select * from FriendRelation where user_id1=target and user_id2=self for update" is not empty) {
"delete from FriendRelation where user_id1=target and user_id2=self";
}
commit;
}
,但是我不确定这种方式是否会导致僵局和/或意外的错误发生,因为我在每个更新操作和表格上锁定记录具有独特的约束。我已经考虑了一段时间,但无法想到这样的情况,这种情况是行不通的,只是有一种直觉,感觉这种方式可能会引起一些问题。
如果这确实是不安全的,我将使用两个单独的记录来为以下两个方向使用,这是微不足道的,但需要两次存储。
I have a friend-relation table as follows:
CREATE TABLE `FriendRelation` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id1` bigint(20) unsigned NOT NULL,
`user_id2` bigint(20) unsigned NOT NULL,
`is_both_way` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY (`user_id1`, `user_id2`),
) ENGINE=InnoDB;
The friend relations are like Twitter where one can follow another user in a one-way fashion. Only when both users follow each other they can exchange private messages. It is intended that millions of rows are to be inserted.
In my intended usage when Alice follows Bob a row will be inserted with user_id1=Alice's Id
, user_id2=Bob's Id
, and is_both_way=0
. When Bob follows back the is_both_way
flag is set to 1.
Now if Alice unfollows Bob I am thinking of SWAPPING the user_id1
and user_id2
while changing the is_both_way
flag back to 0.
Basically I have two procedure psudocodes
function follow(self, target) {
begin transaction;
if ("select * from FriendRelation where user_id1=self and user_id2=target" is not empty) {
do nothing;
} elseif ("select * from FriendRelation where user_id1=target and user_id2=self for update" is not empty) {
"update FriendRelation set is_both_way=1 where user_id1=target and user_id2=self";
} else {
"insert into FriendRelation (user_id1, user_id2, is_both_way) values (self, target, 0)";
}
commit;
}
function unfollow(self, target) {
begin transaction;
if ("select * from FriendRelation where user_id1=self and user_id2=target for update" is not empty) {
"update FriendRelation set is_both_way=0, user_id1=target, user_id2=self where user_id1=self and user_id2=target";
} elseif ("select * from FriendRelation where user_id1=target and user_id2=self for update" is not empty) {
"delete from FriendRelation where user_id1=target and user_id2=self";
}
commit;
}
However I am not sure whether this way can cause deadlocks and/or unintended bugs to happen as I am locking the records for every update operation and the table has a unique constraint. I have thought for a while but couldn't think of a case where this does not work but just have a gut feeling that this way might cause some problems.
If this is indeed unsafe I would resort to using two separate records for the two direction of following which is trivially safe but takes two times storage.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论