[debug]记一次竞态更新bug的解决
公司的django项目,有一个旧接口,使用POST方法更新用户的一种记录型数据。
这个接口的历史有点长,最早的时候没有那么多需求,只会更新两个布尔字段。后来,加入一个需要高频次记录的字段。这些字段都属于同一个model。
然后,偶然被发现有时更新会失败的情况。
Debug
开始debug,步骤是这样的:
- 观察nginx请求日志,观察每次POST的参数(我们记录了request_body),肉眼编译代码,尝试找出漏洞。看不出,失败!
- 编写单元测试,将日志中的数据,模拟成testcase,对接口反复测试。没有重现,失败!
- 准备查看mysql日志...
- 突然有了灵感。重新观察日志,发现一个特点,客户端有时会并发请求两个不同payload,但是更新同一对象的请求。原来是race condition!
解决方法
model.save(update_fields=['...'])
解析
虽然这个接口是POST,但是其实它属于PATCH更新,或者说局部更新。
而之前的代码中,使用的是全量更新。
这就导致了: 在两个同时进行的更新操作中,前面完成的一次更新,会被后一次更新覆盖。 因为后一次中对象的数据都是更新前的,所以第一次更新的效果都会恢复。
Tips
Model.save(force_insert=False, force_update=False, using=DEFAULT_DB, update_fields=None)
force_insert & force_update
django的model一般会根据instance是否有主键,决定是INSERT还是UPDATE。
但是,你可以使用这两个参数来强制选择你要执行的方式.
force_insert不算很有用,你也可以确认对象是否有pk,有的话就删除它,然后来执行强制INSERT。
不过,force_update应该算很有用。在django中,大多数时候UPDATE都需要先找到对象,然后再执行更新。这样稍微有点性能的浪费,如果有类似mongo的upsert功能就好了。
用django实现的upsert:
def upsert(instance, pk, **kwargs):
# 注意需要指定pk,除非你的model中的pk是自动生成的(auto_increment不算)
type(instance)(pk=pk, **kwargs).save(force_update=True)
不过上面的方式还有点问题,如果你在kwargs中没有指定model的所有字段,那么这些字段会被重设回默认值。
update_fields
这个参数,等于force_update的加强版。它代表只更新指定的几个字段,没有指定的字段就让它们保持原样好了,也就是等于REST概念中的PATCH更新。
def upsert(instance, pk, **kwargs):
type(instance)(pk=pk, **kwargs).save(update_fields=list(kwargs.keys()))
PATCH更新的好处很多,不止是预防了bug,还能减少payload数据量,增加性能。
为什么不用Queryset.update()
不是不用,只是这个批量更新接口不会调用.save(),也就导致了你在.save()中放的hook也不会被调用。
而且批量更新也不会触发django signals,详情请搜索我翻译的相关文章.
[debug]记一次竞态更新bug的解决的更多相关文章
- iOS 10 的一个重要更新-线程竞态检测工具 Thread Sanitizer
本文介绍了 Xcode 8 的新出的多线程调试工具 Thread Sanitizer,可以在 app 运行时发现线程竞态. 想想一下,你的 app 已经近乎大功告成:它经过精良的打磨,单元测试全覆盖. ...
- MySQL 如何在一个语句中更新一个数值后返回该值 -- 自增长种子竞态问题处理
什么是竞态问题? 假设有一个计数器,首先当前值自增长,然后获取到自增长之后的当前值.自增长后的值有可能被有些操作用来当做唯一性标识,因此并发的操作不能允许取得相同的值. 为什么不能使用使用UPDATE ...
- 竞态条件 race condition data race
竞态条件 race condition Race condition - Wikipedia https://en.wikipedia.org/wiki/Race_condition A race c ...
- linux设备驱动归纳总结(四):4.单处理器下的竞态和并发【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-67005.html linux设备驱动归纳总结(四):4.单处理器下的竞态和并发 xxxxxxxxxx ...
- Linux内核分析(七)----并发与竞态
原文:Linux内核分析(七)----并发与竞态 Linux内核分析(七) 这两天家里的事好多,我们今天继续接着上一次的内容学习,上次我们完善了字符设备控制方法,并深入分析了系统调用的实质,今天我们主 ...
- 漫画|Linux 并发、竞态、互斥锁、自旋锁、信号量都是什么鬼?(转)
知乎链接:https://zhuanlan.zhihu.com/p/57354304 1. 锁的由来? 学习linux的时候,肯定会遇到各种和锁相关的知识,有时候自己学好了一点,感觉半桶水的自己已经可 ...
- UNIX高级环境编程(10)进程控制(Process Control)- 竞态条件,exec函数,解释器文件和system函数
本篇主要介绍一下几个内容: 竞态条件(race condition) exec系函数 解释器文件 1 竞态条件(Race Condition) 竞态条件:当多个进程共同操作一个数据,并且结果依赖 ...
- java多线程——竞态条件与临界区 学习笔记
允许被多个线程同时执行的代码称作线程安全的代码.线程安全的代码不包含竞态条件.当多个线程同时更新共享资源时会引发竞态条件.因此,了解 Java 线程执行时共享了什么资源很重要. 一.局部变量(函数内定 ...
- 【Linux开发】linux设备驱动归纳总结(四):4.单处理器下的竞态和并发
linux设备驱动归纳总结(四):4.单处理器下的竞态和并发 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
随机推荐
- mssql的 for xml path 与 mysql中的group_concat类似MSSQL For xml Path
/****** Script for SelectTopNRows command from SSMS ******/ SELECT D_ID,[D_Name] as Name FROM [LFBMP ...
- DirectX11 With Windows SDK--05 键盘和鼠标输入
前言 提供键鼠输入可以说是一个游戏的必备要素.在这里,我们不使用DirectInput,而是使用Windows的消息处理机制,不过要从头开始实现会让事情变得很复杂.DXTK提供了鼠标输入的Mouse. ...
- 【leetcode-84】 柱状图中最大的矩形
(1pass,比较简单的hard) 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每 ...
- thymeleaf 基础
(一)Thymeleaf 是个什么? 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完全替代 JSP .相较与其他的模板引擎,它有如下 ...
- VMware Workstation Pro 14 虚拟机安装教程
准备学习一下linxus,可不想双系统,那么只有虚拟机这条路了.故在此记录一下安装VMware的过程. 一.下载VMware 我用的是VMware Workstation Pro 14(其他版本也可以 ...
- HDU 1038(速度里程计算 **)
题意是已知车轮的直径,圈数和时间,求所行驶的里程和速度. 单位换算,代码如下: #include <bits/stdc++.h> using namespace std; const do ...
- mysql表基本查询
第一节 -- or # 单行注释/***多行注释*/ -- c创建数据库examCREATE DATABASE exam; USE exam; /*创建部门表*/CREATE TABLE dept( ...
- sql注入问题-视图-事物-以及存储过程(可视化工具)
可视化工具(了解) 可视化工具 workbench 视图 视图 是一张虚拟的表 语法: create view 视图表名 as select * from t1; 作用: .他是执行as 后面的sql ...
- lua 设置文件运行的环境
背景 在一个lua文件中书写的代码, 使用的变量, 需要设置其运行环境. 目的: 1. 不破坏全局环境. 2. 限定文件所使用的环境, 作为沙箱功能. 解法 限定运行空间环境的文件: local m ...
- 关于mirai的一些研究
关于mirai的一些研究 0x01.源码编译: 配置好对应的go开发环境,即可进行编译,生成了主要的文件 badbot为僵尸节点的可执行文件,cnc为主控端的可执行文件,其它一些为辅助工具. 如下图所 ...