美文网首页
数据库重复数据bug记

数据库重复数据bug记

作者: __XY__ | 来源:发表于2018-06-19 14:29 被阅读0次

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

相关文章

网友评论

      本文标题:数据库重复数据bug记

      本文链接:https://www.haomeiwen.com/subject/ciraeftx.html