MySQL有哪些实现方式?何为插入,何为更新?

可能很多小伙伴会说:我们开发过程中,会遵循阿里开发手册中的规约,其中有一条规约如下:

MySQL有哪些实现方式?何为插入,何为更新?

我们不用外键了,也就不会出现前面的 [Err] 1451 错误了

其实阿里开发手册中的这条规约,不是说不让我们用外键,而是说不用数据库层面的外键约束,在应用代码层面解决外键逻辑

用数据库层面的外键,问题提示的很明显,也不会产生脏数据

而应用层解决外键,反而使外键约束的数据一致性问题更隐晦,产生脏数据,如下

MySQL有哪些实现方式?何为插入,何为更新?

从此我们踏上了修数据的不归路

2、主键加速自增

========

很多情况下,我们的主键是 int 或者 bigint 类型,并且设置成了自增

不管是 int 还是 bigint ,都有一个最大值,如果一直自增下去,总有一天会达到最大值(可能到地老天荒也达不到这个值)

replace into 的更新是先删除再插入,会导致主键自增 1(照理来说,更新是不应该导致主键自增 1)

如果更新频率远远大于插入频率,本不用考虑的自增主键用完的问题,可能就需要考虑了

另外也会导致主键不连续,主键值跳跃式的出现在表中

3、主从切换问题

========

master:master-local ,slave:slave-192.168.0.112 ,同步库:my_project

MySQL有哪些实现方式?何为插入,何为更新?

从上图可以看出,主从复制是正常的

接下来我们看看 replace into 对主从复制有什么影响

MySQL有哪些实现方式?何为插入,何为更新?

此时 master 与 slave 上的

t_ware_last_delivery_price 的下一个非手工指定的主键都是 11( AUTO_INCREMENT=11 ),两者是一致的

我们在 master 上使用 replace into 更新一条记录

MySQL有哪些实现方式?何为插入,何为更新?

master 与 slave 的数据是一致的,但是 master 上的下一个自增主键是 AUTO_INCREMENT=12 ,而 slave 上却是 AUTO_INCREMENT=11

可能会有人觉得:数据一致就行,下一个自增主键不一致有什么关系?

我们来想一下这个问题:如果 master 库崩了,我们会怎么做?会将 slave 提升为 master

此时问题就来了: slave 提升成 master 之前,实际数据的 id 已经到了 11 ,但其 AUTO_INCREMENT=11 ,也就说下一个自增主键是 11

那么下一条不指定 id 值的新纪录是插入时就会发生 duplicate key error ,每次冲突之后 AUTO_INCREMENT += 1,直到增长为 max(id) + 1 之后才能恢复正常

INSERT UPDATE

=============

针对 不存在则插入,存在则更新 , MySQL 还提供了另外一种方言实现: INSERT … ON DUPLICATE KEY UPDATE Statement

工作原理

====

如果指定 ON DUPLICATE KEY UPDATE 子句,并且要插入的行将导致唯一索引或主键中出现重复值,则会更新旧行,否则则是插入

例如,如果列 a 被声明为唯一且包含值 1,则以下两条语句具有类似的效果

MySQL有哪些实现方式?何为插入,何为更新?

但是这两条 SQL 的效果并不完全相同,我们以

t_ware_last_delivery_price 为例,来看看它们的区别

我们先来看看 UPDATE

MySQL有哪些实现方式?何为插入,何为更新?

只是对 id = 11 的 last_delivery_price 就行了修改,受影响的行只有 1,不会影响 AUTO_INCREMENT 的值

我们再来看看 INSERT INTO … ON DUPLICATE KEY UPDATE

MySQL有哪些实现方式?何为插入,何为更新?

对 id = 11 的 last_delivery_price 进行了修改,受影响的行是 2,并且 AUTO_INCREMENT=13

此刻,我相信我们有共同的两个疑问

1、为什么受影响的行数是 2,而不是 1

2、自增主键为什么自增了 1( AUTO_INCREMENT 为什么等于 13,而不是原有的 12)

为什么受影响的行数是 2,而不是 1,官方文档有这么一段说明

MySQL有哪些实现方式?何为插入,何为更新?

意思就是:1 表示新插入一行,2 表示更新了一行,0 表示更新前后值未变

我们换个角度来理解,假设让我们来设计,一条 SQL 既能插入,也能更新,我们如何告知用户到底是插入成功了,还是更新成功了?

所以 1,2 仅仅只是用来区分插入和更新,2 并非真正受影响的行数

主键明明没有变化,为什么 AUTO_INCREMENT=13 自增了 1 ?

这和 MySQL 的主键自增的参数有关 innodb_autoinc_lock_mode ,它有 3 个值 0,1,2

MySQL有哪些实现方式?何为插入,何为更新?

mysql5.1 之后其默认值是 1

MySQL有哪些实现方式?何为插入,何为更新?

因为 innodb_autoinc_lock_mode = 1

MySQL有哪些实现方式?何为插入,何为更新?

所以上述 SQL 被当作简单插入处理,在真正修改数据之前就对 AUTO_INCREMENT 自增 1 处理了

批量操作

====

不仅支持单条操作,也支持批量操作

MySQL有哪些实现方式?何为插入,何为更新?

和批量插入类似

有坑

==

因为 innodb_autoinc_lock_mode = 1 是一个折中的选择,一般不会去改它,所以有些需要注意的点

1、主键加速自增

========

与 replace into 类似,即使是更新,也会导致 AUTO_INCREMENT 自增,加速了主键的衰老

同时也会导致主键的跳跃

2、主从切换问题

========

与 replace into 类似, master 上的更新导致 AUTO_INCREMENT 自增,而 AUTO_INCREMENT 又未同步到 slave

当 slave 升级成 master 后,可能会出现 duplicate key error

与 replace into 不同的是,上述两个问题可以通过设置 innodb_autoinc_lock_mode = 0 来避免,因为很多场景下对性能要求并不高。

总结

==

1、如何选择哪种方式

上述三种方式各有优略,代码处理不依赖于具体的数据库,可移植性高,也不会引入特定数据库的在这方面的缺陷

replace into 的方式不推荐(坑有点多),它完全可以由 INSERT UPDATE 替代

INSERT UPDATE 可以减少我们的代码,但它是 MySQL 的拓展实现,只有 MySQL 支持,可移植性差
2、针对 INSERT UPDATE 的 “坑”,我们可以结合具体的业务来设置 innodb_autoinc_lock_mode ,适当地避免它的 “坑”
3、道路千万条,合适第一条
针对某个需求,实现方式往往有很多,我们要做的就是从中找到最适合的那一条

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
g-vyCvzANn-1715850340261)]

[外链图片转存中…(img-L5NyYkgA-1715850340261)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值