业务上有这样的需求,A、B 两个用户,如果互相关注,则成为好友。
设计上是有两张表,一个是 like 表,一个是 friend 表,like 表有 user_id、liker_id 两个字段,我设置为复合唯一索引即 uk_user_id_liker_id。语句执行逻辑是这样的:
以 A 关注 B 为例:
第一步,先查询对方有没有关注自己(B 有没有关注 A)
select * from like where user_id = B and liker_id = A;
如果有,则成为好友
insert into friend;
没有,则只是单向关注关系
insert into like;
但是如果 A、B 同时关注对方,会出现不会成为好友的情况。因为上面第 1步,双方都没关注对方。第 1 步即使使用了排他锁也不行,因为记录不存在,行锁无法生效。请问这种情况,在 MySQL 锁层面有没有办法处理?
即:在并发场景下,同时有两个人,设置为关注对方,就可能导致无法成功加为朋友关系。
模拟出表:
PS:业务根本就是保证“我一定会插入重复数据,数据库一定要要有唯一性约束”,这时直接建唯一索引。不用考虑在“业务开发保证不会插入重复记录”的情况下,着重要解决性能问题的时候,才建议尽量使用普通索引。