[转] MySQL "replace into" 的坑 (5.5 ROW格式)
MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO。
比如有这样一张表:
1 |
|
auto 表有一个自增的 id 字段作为主键,字段 k 有 UNIQUE KEY 做唯一性约束。写入几条记录之后会是这样:
1 |
|
在 slave 节点上是和 master 一致的:
1 |
|
可以看到,写入三条记录之后,auto 表的 AUTO_INCREMENT 增长为 4,也就是说下一条不手工为 id 指定值的记录,id 字段的值会是 4。
接下来使用 REPLACE INTO 来写入一条记录:
1 |
|
可以看到 MySQL 说 “2 rows affected”,可是明明是只写一条记录,为什么呢?这是因为 MySQL 在执行 REPLACE INTO auto (k) VALUES (1) 时首先尝试 INSERT INTO auto (k) VALUES (1),但由于已经存在一条 k=1 的记录,发生了 duplicate key error,于是 MySQL 会先删除已有的那条 k=1 即 id=1 的记录,然后重新写入一条新的记录。
这时候 slave 上出现了诡异的问题:
1 |
|
可以知道,当前表内数据 id 字段的最大值是 4,AUTO_INCREMENT 应该为 5,但在 slave 上 AUTO_INCREMENT 却并未更新,这会有什么问题呢?把这个 slave 提升为 master 之后,由于 AUTO_INCREMENT 比实际的 next id 还要小,写入新记录时就会发生 duplicate key error,每次冲突之后 AUTO_INCREMENT += 1,直到增长为 max(id) + 1 之后才能恢复正常:
1 |
|
没有预料到 MySQL 在数据冲突时实际上是删掉了旧记录,再写入新记录,这是使用 REPLACE INTO 时最大的一个误区,拿之前的例子来说,执行完 REPLACE INTO auto (k, v) VALUES (1, ‘1-1’) 之后,由于新写入记录时并未给 extra 字段指定值,原记录 extra 字段的值就「丢失」了,而通常这并非是业务上所预期的,更常见的需求实际上是,当存在 k=1 的记录时,就把 v 字段的值更新为 ‘1-1’,其他未指定的字段则保持原状,而满足这一需求的 MySQL 方言是 INSERT INTO auto (k, v) VALUES (1, ‘1-1’) ON DUPLICATE KEY UPDATE v=VALUES(v);
鉴于此,很多使用 REPLACE INTO 的场景,实际上需要的是 INSERT INTO … ON DUPLICATE KEY UPDATE,在正确理解 REPLACE INTO 行为和副作用的前提下,谨慎使用 REPLACE INTO。
原文地址:
https://blog.xupeng.me/2013/10/11/mysql-replace-into-trap/
[转] MySQL "replace into" 的坑 (5.5 ROW格式)的更多相关文章
- MySQL "replace into" 的坑
MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO. 比如有这样一张表: CREATE TABLE `au ...
- MySQL "replace into" 的坑以及insert相关操作
下面我们主要说一下在插入时候的几种情况: 1:insert ignore 2:replace into 3:ON DUPLICATE KEY UPDATE 关于insert ignore: 关于rep ...
- MySQL replace into 使用详解 及 注意事项
REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.注意:除非表 ...
- MySQL REPLACE INTO 的使用
前段时间写游戏合服工具时出现过一个问题,源DB和目标DB角色表中主键全部都不相同,从源DB取出玩家数据再使用 replace into 写入目标DB中,结果总有几条数据插入时会导致目标DB中原有的角色 ...
- MySQL replace函数替换字符串语句的用法(mysql字符串替换)
MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪. 最近在研究CMS,在数据转换的时候需要用 ...
- 被mysql中的wait_timeout坑了
今天被mysql里的wait_timeout坑了 网上能搜到很多关于mysql中的wait_timeout相关的文章,但是大多数只是说明了他的作用,而且都说这个参数要配合那个inter ...
- MySQL replace into 说明(insert into 增强版)
MySQL replace into 说明(insert into 增强版) 在插入数据到一个表时,通常是这种情况:1. 先推断数据是否存在: 2. 假设不存在,则插入:3.假设存在,则更新. 在 S ...
- 【踩坑记录】记一次MySQL主从复制延迟的坑
最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...
- Ubuntu 16.04 安装Mysql 5.7 踩坑小记
title:Ubuntu 16.04 安装Mysql 5.7 踩坑小记 date: 2018.02.03 安装mysql sudo apt-get install mysql-server mysql ...
随机推荐
- Hdu 4738 Caocao's Bridges (连通图+桥)
题目链接: Hdu 4738 Caocao's Bridges 题目描述: 有n个岛屿,m个桥,问是否可以去掉一个花费最小的桥,使得岛屿边的不连通? 解题思路: 去掉一个边使得岛屿不连通,那么去掉的这 ...
- Java compiler level does not match the version of the installed Java project facet问题处理
从SVN上下载应用后在Problems面板中提示以下错误信息: Java compiler level does not match the version of the installed Java ...
- MySQL故障处理一例_Another MySQL daemon already running with the same unix socket
MySQL故障处理一例:"Another MySQL daemon already running with the same unix socket". [root@test- ...
- ViewPager(1)FragmentPagerAdapter
FragmentPagerAdapter 适合只有少量的pager,所有pager同时全部存在,不会有被销毁的,page过多很容易内存溢出. 1,代码 1.1 ViewPagerMain.java i ...
- 384 Shuffle an Array 打乱数组
打乱一个没有重复元素的数组.示例:// 以数字集合 1, 2 和 3 初始化数组.int[] nums = {1,2,3};Solution solution = new Solution(nums) ...
- Echarts和Quartz简介
一.Echarts ECharts 是由百度前端团队开发的一款开源的基于 js 图形报表组件,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大 ...
- [ SPOJ RESTACK ] Restacking haybales
\(\\\) Description 给出一个环,每个位置有一个初值 \(A_i\),有一个目标值 \(B_i\),保证 \(\sum A_i=\sum B_i\) 每个位置只能把值分给隔壁的,每次分 ...
- WordPress腾讯云存储搭建教程,完美解决
写在前面的话: 为什么会有今天的话题:WordPress+腾讯云存储? 因为博主不想使用七牛云,也不想使用又拍云,所以才有了今天的话题. 在使用腾讯云存储的过程中是很不顺利的,万幸的是现在终于完美融合 ...
- 内存溢出及Jvm监控工具
内存泄露与内存溢出 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory. 内存泄露 memory leak,是指程序在申请内存后,无 ...
- react Native环境 搭建
react Native的优点:跨平台 低投入高回报 性能高 支持动态更新.一才两用(ios和Android) 开发成本第 代码复用率高.windows环境搭建react Native开发环境1.安装 ...