花店网站建设实训总结,成都设计公司装修,安徽网站建设认准-晨飞网络,建网站中企动力目录 业务场景
业务问题#xff1a;
数据库表设计#xff1a;
like#xff08;关注表#xff09;#xff1a;
friend#xff08;朋友表#xff09;
并发场景下#xff0c;SQL语句执行逻辑
比较 A 和 B 的大小#xff0c;如果 A执行下面的逻辑#xff1a;
数据库表设计
like关注表
friend朋友表
并发场景下SQL语句执行逻辑
比较 A 和 B 的大小如果 A执行下面的逻辑
如果 AB,则执行下面的逻辑
SQL写法详解
参考内容 业务场景
业务上有这样的需求A、B两个用户如果互相关注则成为好友。
业务问题
在并发场景下同时有两个人设置为关注对方就可能导致无法成功加为朋友关系。如下
sessiona喜欢bsessionb喜欢a begin; select * from friend_like where user_id B andliker_id A;(返回空) begin; select * from friend_like where user_id B andliker_id A;(返回空) insert into friend_like (user_id, liker_id) values(B,A);insert into friend_like (user_id, liker_id) values(A,B);commit;commit;
数据库表设计
like关注表
CREATE TABLE friend_like (id int(11) NOT NULL AUTO_INCREMENT,user_id int(11) NOT NULL,liker_id int(11) NOT NULL,relation_ship int(11) NOT NULL,PRIMARY KEY (id),UNIQUE KEY uk_user_id_liker_id (user_id,liker_id)
) ENGINEInnoDB;
friend朋友表
CREATE TABLE friend (id int(11) NOT NULL AUTO_INCREMENT,friend_1_id int(11) NOT NULL,friend_2_id int(11) NOT NULL,UNIQUE KEY uk_friend (friend_1_id,friend_2_id),PRIMARY KEY (id)
) ENGINEInnoDB; relation_ship:
1表示 user id 关注 liker id;
2表示liker id 关注 user id;
3表示互相关注。
并发场景下SQL语句执行逻辑
比较 A 和 B 的大小如果 AB执行下面的逻辑
begin; /*启动事务*/
insert into like(user_id, liker_id, relation_ship) values(A, B, 1) on duplicate key update relation_shiprelation_ship | 1;
select relation_ship from like where user_idA and liker_idB;
/*代码中判断返回的 relation_ship如果是1事务结束执行 commit如果是3则执行下面这两个语句*/
insert ignore into friend(friend_1_id, friend_2_id) values(A,B);
commit;/*提交事务*/
如果 AB,则执行下面的逻辑
begin; /*启动事务*/
insert into like(user_id, liker_id, relation_ship) values(B, A, 2) on duplicate key update relation_shiprelation_ship | 2;
select relation_ship from like where user_idB and liker_idA;
/*代码中判断返回的 relation_ship如果是2事务结束执行 commit如果是3则执行下面这两个语句
*/
insert ignore into friend(friend_1_id, friend_2_id) values(B,A);
commit;
SQL写法详解
这个设计里让“friend_like”表里的数据保证 user id liker id这样不论是A关注B还是B关注A在操作“like”表的时候如果反向的关系已经存在就会出现行锁冲突 然后insert...on duplicate 语句确保了在事务内部执行了这个 SQL语句后就强行占住了这个行锁之后的 select 判断 relation ship 这个逻辑时就确保了是在行锁保护下的读操作。 操作符“|” 是按位或连同最后一句 insert 语句里的 ignore是为了保证重复调用时的幂等性 这样即使在双方“同时”执行关注操作最终数据库里的结果也是 like 表里面有一条关于 A和B的记录而且 relation ship 的值是3并且 friend 表里面也有了A和B的这条记录。
参考内容
15 | 答疑文章一日志和索引相关问题 (geekbang.org)