数据库重复数据bug记

0 bug初现

业务当中有这么一条业务代码:
从数据库中查询用户A相关的记录,如果没有就创建一条。

测试阶段都没有遇到什么问题,然后正在上线后发现,会出现一种情况:用户存在两条数据

1 初步判断

初步推断原因为:网络阻塞情况下,用户点了下按钮没有反映,然后又刷新页面又自动发了一次请求,等网络不阻塞了,两个请求同时到了服务器,然后同时发现数据库中都没有这条记录,于是同时创建了一条。就产生了上面的现象。

2 bug复现模拟

使用脚本模拟十次并发,直接调用 相关函数。

  • 模拟这里碰到了问题,因为flask的函数环境都是默认在单线程中完成的。
    当我们直接因为flask app 里面的特定函数并且去执行的时候,肯定是out_of_app_context报错的。
  • 还是要模拟线上环境,由gunicorn来当服务器托起app,然后使用多进程脚本来模拟并发。
import requests

url = "http://localhost:8000/api/v1/test"

payload = "{}"
headers = {
    'content-type': "application/json",
    'cache-control': "no-cache",
    'postman-token': "665a76a5-f37f-96d9-cdbd-9c7f66f1f6ba"
    }

def r ():
    response = requests.request("POST", url, data=payload, headers=headers)
    print(response.text)

import threading
for i in range(10):
    t = threading.Thread(target=r)
    t.start()

request相关的代码可以直接复制postman里面的code

运行脚本,果然复现出了bug

  File "/home/ubuntu/.virtualenvs/coucou/local/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2827, in one_or_none
    "Multiple rows were found for one_or_none()")
sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one_or_none()

3 解决方式分析

  • 1采用orm的first来筛选,但是没有解决掉数据库数据重复的问题
  • 2 代码层面限于flask线程环境,无法进行锁的操作,也就无法在代码层面解决bug。(非锁的问题,之前的思路想错了)
  • 3 考虑使用mysql数据库锁,因为之前从未实践过mysql的锁,所以以下开始学习。
  • 4 采用unique索引,从数据库层面去解决数据重复的问题。(这才是正确答案)

4 mysql锁初识

  • 参看数据库有用到锁
    show lock tables
  • pass
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 如果我和这个城市分别 会不会有一场雪 凌空飞扬 像烟消云散的爱情 像雨中凋零的柳絮 而桃花刚刚开放 还没有人从树下...
    茱萸茱萸阅读 187评论 5 2
  • 2017.7.15第45天 星期六 阴间小雨 今天上午上完吉他课,儿子回来自己做饭吃的,下午跟同学一块写...
    鑫隆妈妈阅读 236评论 0 0
  • 1.定义输入和输出为: 输入数据格式为:年,月,日,温度。格式为2012,01,01,05 输出数据的格式为:年-...
    _Kantin阅读 887评论 0 1

友情链接更多精彩内容