MYSQL不存在插入 存在更新的解决方法和对比

news2024/11/13 10:47:21

在这里插入图片描述
设置主键id自增,name为唯一索引

一、避免重复插入

insert ignore into(有唯一索引)

关键字/句: insert ignore into,如果插入的数据会导致 UNIQUE索引PRIMARY KEY 发生冲突/重复,则忽略此次操作/不插入数据,例:

INSERT IGNORE INTO `student`(`name`,`age`) VALUES(`Jack`18);

-- row(s) affected

这里已经存在 name='Jack”的数据,所以会忽略新插入的数据,受影响行数为 0,表数据不变

需要注意 主键会自增

当使用了insert ignore into 新增数据,即使没有插入,某些版本的mysql会自增主键。
比如原来有数据1(id为1),你又插入了数据1,但是重复了没插入,之后再插入数据2,此时的数据2的主键为3而非2.
mysql5.7.26不会自增,8.0会自增

如何避免自增?

在MySQL5.7中做INSERT IGNORE时发现, 即使INSERT未成功执行, 表的自增主键却自动加1了, 在某些情况下需要避免这种行为. 需要修改的变量是 innodb_autoinc_lock_mode, 将其设为0后, 在INSERT未成功执行时不会自增主键.

innodb_autoinc_lock_mode在MySQL各版本的默认值

根据MySQL官方手册的说明:

There are three possible settings for the innodb_autoinc_lock_mode configuration parameter. The settings are 0, 1, or 2, for “traditional”, “consecutive”, or “interleaved” lock mode, respectively. As of MySQL 8.0, interleaved lock mode (innodb_autoinc_lock_mode=2) is the default setting. Prior to MySQL 8.0, consecutive lock mode is the default (innodb_autoinc_lock_mode=1).

在MySQL8中, 默认值为 2 (interleaved, 交错), 在MySQL8以前, 准确地说在8之前, 5.1之后, 默认值为 1 (consecutive, 连续), 在更早的版本是 0

innodb_autoinc_lock_mode的说明

这个值主要用于平衡性能与安全(主从的数据一致性), insert主要有以下类型

simple insert 如insert into t(name) values(‘test’)
bulk insert 如load data | insert into … select … from …
mixed insert 如insert into t(id,name) values(1,‘a’),(null,‘b’),(5,‘c’);
innodb_autoinc_lock_mode = 0:

与更高版本的MySQL向后兼容
在这一模式下,所有的insert语句都要在语句开始的时候得到一个表级的auto_inc锁,在语句结束的时候才释放这把锁,一个事务可能包涵有一个或多个语句
它能保证值分配的可预见性,与连续性,可重复性,这个也就保证了insert语句在复制到slave的时候还能生成和master那边一样的值(它保证了基于语句复制的安全)
由于在这种模式下auto_inc锁一直要保持到语句的结束,所以这个就影响到了并发的插入
innodb_autoinc_lock_mode = 1:

这一模式对simple insert做了优化,由于simple insert一次性插入值的个数可以立即确定, 所以mysql可以一次生成几个连续的值用于这个insert语句, 总的来说这个对复制也是安全的(保证了基于语句复制的安全)
这一模式也是MySQL8.0之前的默认模式, 这个模式的好处是auto_inc锁不要一直保持到语句的结束, 只要语句得到了相应的值后就可以提前释放锁
innodb_autoinc_lock_mode = 2:

由于这个模式下已经没有了auto_inc锁, 所以这个模式下的性能是最好的, 但是它也有一个问题, 就是对于同一个语句来说它所得到的auto_incremant值可能不是连续的
现在mysql已经推荐把二进制的格式设置成row, 所以在binlog_format不是statement的情况下这个模式可以达到最好的性能

insert if not exists(无唯一索引)

数据字段没有设置主键或唯一索引,当插入数据时,首先判断是否存在这条数据,不存在正常插入,存在则忽略。现在我把主键和唯一索引都去掉了。完整sql为

insert into tacs_staff.user(user_name,address) select '张三','天津' from dual where not exists (select user_name from tacs_staff.user where user_name='张三');

二、不存在则插入,存在则更新

on duplicate key update

如果插入的数据会导致UNIQUE 索引或PRIMARY KEY发生冲突/重复,则执行UPDATE语句,例:

INSERT INTO student(name, age) VALUES(‘Jack’, 19)
ON DUPLICATE KEY
UPDATE age=19; – If will happen conflict, the update statement is executed

– 2 row(s) affected

这里受影响的行数是2,因为数据库中存在name='Jack’的数据,如果不存在此条数据,则受影响的行数为1

可能遇到死锁

bug在5.7.26以及8.0.15版本上已经修复了,当插入数据时,不会在形成间隙锁

但是此方法也有坑,如果表中不止一个唯一索引的话,在特定版本的mysql中容易产生dead lock(死锁)

当mysql执行INSERT ON DUPLICATE KEY的 INSERT时,存储引擎会检查插入的行是否会产生重复键错误。如果是的话,它会将现有的
行返回给mysql,mysql会更新它并将其发送回存储引擎。当表具有多个唯一或主键时,此语句对存储引擎检查密钥的顺序非常敏感。根据这个顺序,
存储引擎可以确定不同的行数据给到mysql,因此mysql可以更新不同的行。存储引擎检查key的顺序不是确定性的。例如,InnoDB按照索引添加到
表的顺序检查键。

insert … on duplicate key 在执行时,innodb引擎会先判断插入的行是否产生重复key错误,如果存在,在对该现有的行加上S(共享锁)锁,如果返回该行数据给mysql,然后mysql执行完duplicate后的update操作,然后对该记录加上X(排他锁),最后进行update写入。
如果有两个事务并发的执行同样的语句,那么就会产生death lock

mysql官方描述很简单

An INSERT … ON DUPLICATE KEY UPDATE statement against a table having more than one unique or primary key is also marked as unsafe. (Bug #11765650, Bug #58637)

insert on duplicate key update 如果命中主键或者唯一键索引,加行锁,未命中加gap锁,即会阻塞插入数据
在这里插入图片描述
过程分析
insert … on duplicate key 在执行时,innodb引擎会先判断插入的行是否产生重复key错误,如果存在,在对该现有的行加上S(共享锁)锁,如果返回该行数据给mysql,然后mysql执行完duplicate后的update操作,然后对该记录加上X(排他锁),最后进行update写入。
如果有两个事务并发的执行同样的语句,那么就会产生death lock,如:
在这里插入图片描述
低版本的解决方法

  1. 尽量不对存在多个唯一键的table使用该语句
  2. 在有可能有并发事务执行的insert 的内容一样情况下不使用该语句。将批量insert on duplicate key update,拆分成多个语句。保证一次事务中不要插入过多值,将多个数据,变成多个sql,执行插入。可以有效的减少死锁命中的发生。
  3. 重试:死锁不可怕,当出现死锁发生时,多执行重试操作可以有效保证插入成功,更新不丢失。
  4. 线程池多线程并发执行改为单线程排队处理。

replace into(先删除再插入)

在这里插入图片描述
replace into 会根据唯一索引或主键进行判断,如果存在则覆盖写入字段,如果不存在则新增。
此方法有坑,如果主键是自增的,且通过唯一索引来进行操作时,主键会变更,该方法底层是先进性delete,在insert
如果有子表依赖的话不建议使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode.1664 生成平衡数组的方案数

题目链接 Leetcode.1664 生成平衡数组的方案数 题目描述 给你一个整数数组 nums。你需要选择 恰好 一个下标(下标从 0 开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 比方说,如果 nums[6,1,7,4,1]nums [6,1…

spark转化操作

文章目录转化操作Transformer算子概念单RDD转换函数多RDD转换函数map与flatmap转化操作 由于spark的惰性计算特性,RDD只有在第一次行动操作中被用到时才会真正进行计算,因此我打算将文章内容分为"转化操作"和"行动操作"两部分&…

【web】微信小程序笔记小结(视图与逻辑)

过完年回来干正事了orz 来源:黑马程序员前端微信小程序开发教程 目录 I. 页面导航 ① 概念 ② 导航方式 1)声明式导航 ※※ 导航到 tabBar 页面 ※※ 导航到非 tabBar 页面 ※※ 后退导航 2)编程式导航 ※※ 导航到 tabBar 页面…

Nature立新规:ChatGPT等大模型不可以成为作者

众所周知,AI 的超参数决定着模型学习效果和速度。相比普通机器学习任务,深度学习需要的训练时间较长,因此调参技巧就显得尤为重要。 但鉴于深度学习「炼丹」的特性,不同的模型需要不同的超参数,而每个超参的意义又不同…

【头歌】汉诺塔(Hanoi)的递归算法

任务描述本关任务:汉诺塔(Hanoi)的递归算法。相关知识相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标&a…

C语言中数组变量作为函数参数传值的两种方式:数组类型 指针类型 以及“C语言中数组变量(名)的本质是指针变量”

文章目录Intro & SummaryCode & Output运行截图Code关于数组长度在被调函数中的计算错误运行截图 & 警告信息Code数组变量是一类特殊的、指向自己的指针变量Intro & Summary 我在 main 函数中定义了一个数组,要将该数组作为参数传递给其他方法。那…

Lesson 4.3 梯度下降(Gradient Descent)基本原理与手动实现

文章目录一、梯度下降基本原理与学习率1. 数据背景与最小二乘法求解2. 一维梯度下降基本流程2.1 参数移动第一步2.2 梯度下降的多轮迭代3. 梯度下降算法特性与学习率二、梯度下降一般建模流程与多维梯度下降1. 多维梯度下降与损失函数可视化2. 梯度下降计算流程3. 二维梯度下降…

jvm学习的核心(四)---执行引擎和字符串

知识点总结于b站宋红康老师,视频链接 文章目录1.执行引擎1.1.执行引擎概述1.2.执行引擎的工作流程1.3.jvm的解释器和即时编译器(JIT)1.3.1.解释器,即时编译器概述1.3.2.常见即时编译器1.3.3.热点代码探测1.String Table1.1 string…

Go语言基础入门第三章

常量 常量是一个简单值的标识符,在程序运行时,不会被修改的量。 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。 const identifier [type] value可以省略类型说明符[type],因为编译器…

法律常识(三)《合同法》中的借款合同租赁合同摘录

目录 参考 一、借款合同 二、租赁合同 参考 中华人民共和国合同法 一、借款合同 第一百九十六条 借款合同是借款人向贷款人借款,到期返还借款并支付利息的合同。 第一百九十七条 借款合同采用书面形式,但自然人之间借款另有约定的除外。借款合同…

瑞吉外卖 对象转换器 公共字段自动填充 文件上传/下载

https://blog.csdn.net/weixin_43715214/category_12022798.html大佬记录项目介绍day01功能架构(1)用户层本项目中在构建系统管理后台的前端页面,我们会用到H5、Vue.js、ElementUI等技术。而在构建移动端应用时,我们会使用到微信小…

Red Giant Magic Bullet Suite介绍

Red Giant Magic Bullet Suite介绍什么是Magic Bullet SuiteMagic Bullet Suite功能介绍什么是Magic Bullet Suite Magic Bullet Suite是电影制作人不可或缺的一套调色降噪插件,它能够为您制作出和好莱坞一样的效果,为电影制作人提供专业的色彩校正。可…

excel函数应用:最简单的条件求和函数DSUM

SUM系列求和函数是我们日常工作中最常用的函数,相信大部分朋友对SUMIF、SUMIFS、SUMPRODUCT等函数都已经比较熟悉了。但是有一个求和函数大家可能都不熟悉,它就是DSUM函数,用于求数据库中记录的满足给定条件的的字段(列&#xff0…

在中国社科院与美国杜兰大学金融管理硕士项目就读,重焕青春活力

在职场摸爬滚打多年后的你,是否有觉得内心疲惫? 是否进入到职场倦怠期?今天是春节后的首个工作日,新的一年意味着新的开始。你有想过在职继续攻读硕士学位吗?在中国社科院与美国杜兰大学金融管理硕士项目就读&#xff…

vue中实现打印

一、VUE 集成 LODOP插件打印 VUE 集成LODOP插件打印 Lodop、C-Lodop使用说明及样例 C-Lodop插件官网:功能演示 - Lodop和C-Lodop官网主站 参考文章:VUE 集成 LODOP插件打印_廷贺的博客-CSDN博客 二、winodw.print() 打印 print() 方法用于打印当前…

vs2015软件打包及常见问题解决方法

一、如程序文件是64位,而项目设置32位,打包项目编译时遇到如下问题 解决办法:选择打包程序项目的属性窗口设置TargetPlatform属性为对应的值,本项目的文件是64位的所以设置打包生成的程序为64位的,如下: …

【可解释性机器学习】排列重要性(Permutation Importance)及案例分析详解

Permutaion Importance:排列重要性引言工作原理代码示例排列重要性结果解读模型检验特征选择补充分析Partial Dependency PlotSharpley ValueLIME总结参考资料当训练得到一个模型之后,除了对模型的预测感兴趣之外,我们往往还想知道模型中哪些…

DDOS渗透与攻防(三)之socktress攻击

系列文章 DDOS渗透与攻防(一)之拒绝服务攻击概念介绍 DDOS渗透与攻防(二)之SYN-Flood攻击 socktress攻击 攻击协议原理介绍说明-socktress 2008年有Jack C.Louis发现,针对TCP服务的拒绝服务攻击: 消耗被攻击目标系统资源,与攻击目标建立…

xml配置JedisUtil

一.背景 习惯了Bean注解方式往sping容器中注入对象,现使用xml方式注入Bean对象总结下,顺便用帮女朋友解决的Jedis问题当做案例来总结。 二.配置JedisPool 从源码来看,JedisPool的构造函数有N多种 我们使用如下的构造函数来实例化JedisPool…

docker部署Nginx和Tomcat

文章目录 前言 目录 文章目录 前言 一、docker部署Nginx 二、docker部署Tomcat 总结 一、docker部署Nginx 下载镜像:docker pull nginx 后台运行镜像 -d 后台运行 --name"nginx01" 给容器命名 -p 宿主机端口:容器内部端口 docker run -d --name"…