1.背景:

  每天0点定时任务统计数据,实现目标是统计时如果没有今天的统计数据,那就执行insert操作 如果存在那就执行update操作;

代码逻辑

1 if(报表存在){
2 update();
3 }else{
4 insert();
5 }

上线跑了多天后 发现有时候会出现同一天的统计数据有2条

经过分析后

  发现当0点定时任务跑的时候,存在用户登录(登录需要统计,需要更新报表),因为0点的时候,数据库都没记录,所以两者都判断了insert操作,造成数据库有2条相同数据(只有登录数量的字段不一样,其他字段都一样)

2.解决方案:

  说实话,第一反应是给数据表加锁。laravel提供了2个锁:sharedLock和lockForUpdate.经过仔细研究分析后发现,这2个锁并不能解决我目前的需求,原因如下:

  • sharedLock 对应的是 LOCK IN SHARE MODE
  • lockForUpdate 对应的是 FOR UPDATE

  这2个锁都是避免同一行数据被其他transaction进行update()的。

  • sharedLock 不会阻止其他 transaction 读取同一行
  • lockForUpdate 会阻止其他 transaction 读取同一行 (需要特别注意的是,普通的非锁定读取读取依然可以读取到该行,只有 sharedLock 和 lockForUpdate 的读取会被阻止。)

  但是我现在的实际情况都没有读到数据,所以都不能满足。

  后来实在没办法想到了表锁,对,就是把全表都锁定了。但是这个效率性能实在太差了,而且在LOCK TABLE 和UNLOCK TABLE之间有异常,会导致锁无法释放。潜在问题很严重,所以还是不打算用这个方法。

INSERT IGNORE

  经查阅大量资料(疯狂百度)后发现了insert ignore。insert ignore 如果存在数据,那么则忽略新数据

REPLACE INTO

  replace into 表示插入替换数据,表中如果有PrimaryKey或者unique索引的话,数据库如果已存在数据,则用新数据替换,如果没有数据则和insert into一样。

上面2个方法固然好,但是存在数据丢失的问题,还是放弃了。

INSERT INTO

    最终的解决办法居然回到了最原始的sql语句。insert into表示插入数据,数据库会检查主键(PrimaryKey),如果出现重复会报错;

  对就是利用这个主键报错的机制,解决了的需求。就是在每次插入数据的时候把下一个自增id也插入进去。因为我们平时插入数据都是不用管自增id的,所以laravel都没有获取下一个自增id的封装方法。没办法,自己动手丰衣足食。

//获取下一个自增id,方法还是很简单的

1 public static function getIncrementId()
2 {
3 $id = self::query()
4 ->orderByDesc('id')
5 ->value('id');
6 return ++$id;
7 }
 1           try {
2 $report = DailyReport::getReport($customer->id, 1);
3 if (!$report) {
4 $id = DailyReport::getIncrementId();
5 DailyReport::create([
6 'customer_id' => $customer->id,
7 'report_date' => Carbon::today(),
8 'id' => $id,//把id也插入
9 ...
10 ]);
11 }
12 } catch (\Exception $exception) {
13 if (23000 == $exception->getCode()){//这里捕获主键重复的错误,然后做相关逻辑的操作 23000后来发现好像也别的sql错误也会报,记得优化
14 //do something
15 }else{
16 LogManagers::error($exception);
17 }
18 }

上面就是解决的代码。最终的解决办法还是利用了主键重复的错误来解决问题。

本文属于个人原创,欢迎转载,转载请附链接:https://www.cnblogs.com/x-x-j/p/13491564.html

laravel 解决mysql插入相同数据的问题的更多相关文章

  1. mysql 插入/更新数据

    mysql 插入/更新数据 INSERT 语句 1.一次性列出全部字段的值,例如: INSERT INTO student VALUES('Chenqi','M', 29); INSERT INTO ...

  2. 解决mysql导入导出数据乱码问题

    最近在linux上面用mysqldump导出数据,放在windows系统中导入就会出现中文乱码,然后就会导致出现: Unknown MySQL server host和Can't connect to ...

  3. 通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    原文:[原创]通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 'incorrect string value: '\xF0... 这篇blog重点在解决问题,如果你对 ...

  4. php 解决MySQL插入数据出现 Incorrect string value: '\xF0\x9F\x92\x8BTi...'错误

    在项目中向MySQL插入数据时.发现数据插入不完整,通过调试,发现插入语句也没什么特殊的错误. 可是就是差不进去,于是就打开mysqli错误的调试 $ret = mysqli_query($this- ...

  5. MySQL 插入 中文数据乱码解决

    问题描述: 1.在命令行中进行插入,没有问题.但是显示存在部分乱码 2.在JDBC中插入成功.中文是直接以“??”形式显示. 通过Navicat客户端查看 与在网页中看到的一一致,说明读取没有问题,问 ...

  6. MySQL插入中文数据出现?号

    原文转载自:https://blog.csdn.net/LynneZoe/article/details/79174119 运行环境:win10 mysql版本:Mysql5.6 做一个项目的时候,向 ...

  7. 【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    这篇blog重点在解决问题,如果你对字符编码并不是特别了解,建议先看看 < [原创]通俗易懂地解决中文乱码问题(1) --- 跨平台乱码 >. 当然,如果只是针对解决这个Mysql插入报错 ...

  8. [转载]mysql插入大量数据

    mysql的批量数据格式, 比如 INSERT INTO TABLES (LABLE1,LABLE2,LABLE3,...)  VALUES(NUM11,NUM12,NUM13,...),  (NUM ...

  9. C API向MySQL插入批量数据的快速方法——关于mysql_autocommit

    MySQL默认的数据提交操作模式是自动提交模式(autocommit).这就表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行.我们可以通过设置autocommit的值改变是否是自 ...

随机推荐

  1. TCP/IP协议学习-1.概述

    目录 TCP/IP协议概述 分层 延伸知识 FTP例子 为什么需要网络层和传输层 TCP/IP的分层 封装 分用 总结 本文主要摘抄自书籍<TCP/IP详解卷一:协议>与TCP协议相关内容 ...

  2. 1.3.1 apache的配置(下)

    (1)httpd.conf的配置 使用文本编辑工具(推荐使用Editplus.UltraEdit等工具),打开httpd.conf. 其中,行首为#的部分为注释部分,不会被apache服务器程序进行读 ...

  3. 学习java的第二天

    Java第二天 标识符 标识符开头只能以字母和_开头 严格区分大小写 不能以关键词命名 变量 变量是什么:就是可以变化的量 Java是一种强类型语言,定义变量必须声明后才能使用 Java变量是程序中最 ...

  4. Element 文档中的 Markdown 解析

    Element 的文档站是讲Markdown解析成vue组件在页面中渲染出来,转换过程如下图所示: 红框部分势必要对 Markdown 进行特殊的订制,订制过的 Markdown 像下面这样. ::: ...

  5. springboot的4种属性注入

    1.Autowired注入 2.构造方法注入 3.@Bean方法形参注入 4.直接在@Bean方法上使用注解@ConfigurationProperties(prefix="jdbc&quo ...

  6. dubbo使用和配置讲解

    1. 分布式系统中相关概念 1.1 互联网项目特点及目标 1.1.1 特点: 用户多 流量大.并发高 海量数据 易受攻击 功能繁琐 变更快 1.1.2 指标及相关目标 互联网项目三高目标:高并发.高可 ...

  7. RichTextBox FlowDocument类型操作

      最近研究微信项目,套着web版微信协议做了一个客户端,整体WPF项目MVVM架构及基本代码参考于:http://www.cnblogs.com/ZXdeveloper/archive/2016/1 ...

  8. 漏洞复现-ActiveMq任意文件写入漏洞(CVE-2016-3088)

          0x00 实验环境 攻击机:Win 10 靶机也可作为攻击机:Ubuntu18 (docker搭建的vulhub靶场) 0x01 影响版本 未禁用PUT.MOVE等高危方法的ActiveM ...

  9. CRLF注入漏洞 -配置错误

    漏洞分析参考 https://i-beta.cnblogs.com/posts/edit 什么是CRLF? CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII ...

  10. go中sync.Once源码解读

    sync.Once 前言 sync.Once的作用 实现原理 总结 sync.Once 前言 本次的代码是基于go version go1.13.15 darwin/amd64 sync.Once的作 ...