码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • mysql:如何设计互相关注业务场景


    目录

    业务场景

    业务问题:

    数据库表设计:

    like(关注表):

    friend(朋友表) 

    并发场景下,SQL语句执行逻辑

    比较 A 和 B 的大小,如果 A执行下面的逻辑:<>

    如果 A>B,则执行下面的逻辑:

    SQL写法详解:

    参考内容:


    业务场景

    业务上有这样的需求,A、B两个用户,如果互相关注,则成为好友。

    业务问题:

    在并发场景下,同时有两个人,设置为关注对方,就可能导致无法成功加为朋友关系。如下:

    session(a喜欢b)session(b喜欢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(关注表):
    1. CREATE TABLE `friend_like` (
    2. `id` int(11) NOT NULL AUTO_INCREMENT,
    3. `user_id` int(11) NOT NULL,
    4. `liker_id` int(11) NOT NULL,
    5. `relation_ship` int(11) NOT NULL,
    6. PRIMARY KEY (`id`),
    7. UNIQUE KEY `uk_user_id_liker_id` (`user_id`,`liker_id`)
    8. ) ENGINE=InnoDB;
    friend(朋友表) 
    1. CREATE TABLE `friend` (
    2. `id` int(11) NOT NULL AUTO_INCREMENT,
    3. `friend_1_id` int(11) NOT NULL,
    4. `friend_2_id` int(11) NOT NULL,
    5. UNIQUE KEY `uk_friend` (`friend_1_id`,`friend_2_id`),
    6. PRIMARY KEY (`id`)
    7. ) ENGINE=InnoDB;

     relation_ship: 

    1,表示 user id 关注 liker id;

    2,表示liker id 关注 user id;

    3,表示互相关注。

    并发场景下,SQL语句执行逻辑

    比较 A 和 B 的大小,如果 A
    1. begin; /*启动事务*/
    2. insert into `like`(user_id, liker_id, relation_ship) values(A, B, 1) on duplicate key update relation_ship=relation_ship | 1;
    3. select relation_ship from `like` where user_id=A and liker_id=B;
    4. /*代码中判断返回的 relation_ship,
    5. 如果是1,事务结束,执行 commit
    6. 如果是3,则执行下面这两个语句:
    7. */
    8. insert ignore into friend(friend_1_id, friend_2_id) values(A,B);
    9. commit;/*提交事务*/
    如果 A>B,则执行下面的逻辑:
    1. begin; /*启动事务*/
    2. insert into `like`(user_id, liker_id, relation_ship) values(B, A, 2) on duplicate key update relation_ship=relation_ship | 2;
    3. select relation_ship from `like` where user_id=B and liker_id=A;
    4. /*代码中判断返回的 relation_ship,
    5. 如果是2,事务结束,执行 commit
    6. 如果是3,则执行下面这两个语句:
    7. */
    8. insert ignore into friend(friend_1_id, friend_2_id) values(B,A);
    9. 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)

  • 相关阅读:
    【从零开始学微服务】05.微服务的优势和不足
    44.(前端)修改菜单路由地址
    白噪声,有色噪声的定义、特性及其MATLAB仿真
    设计模式再探——适配器模式
    JS基础
    VCS工具学习笔记(6)
    使用openssl rand随机生成MAC地址的方法
    [附源码]JAVA毕业设计健康生活网站(系统+LW)
    【跨境电商】使用补货电子邮件营销策略来鼓励重复购买
    《棒球动漫》:无愧的青春·棒球1号位
  • 原文地址:https://blog.csdn.net/weixin_43522117/article/details/132794278
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号