为什么不建议使用ON DUPLICATE KEY UPDATE?
背景
update tb_user
<trim prefix="set" suffixOverrides=",">
<trim prefix="name = case" suffix="end,">
<foreach collection="list" item="i" index="index">
when id= #{i.id,jdbcType=VARCHAR} then #{i.name,jdbcType=VARCHAR}
</foreach>
</trim>
<trim prefix="weight = case" suffix="end,">
<foreach collection="list" item="i" index="index">
when id= #{i.id,jdbcType=VARCHAR} then #{i.weight,jdbcType=DECIMAL}
</foreach>
</trim>
<trim prefix="high = case" suffix="end,">
<foreach collection="list" item="i" index="index">
when id= #{i.id,jdbcType=VARCHAR} then #{i.high,jdbcType=DECIMAL}
</foreach>
</trim>
</trim>
where id in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item.id,jdbcType=VARCHAR}
</foreach>
</update>
官方资料
进行验证
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键ID',
`b` int(11),
`c` int(11),
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='临时测试表'
| 验证主键插入并更新功能
ON DUPLICATE KEY UPDATE c=c+1;
ON DUPLICATE KEY UPDATE c=c+1;
| 验证多字段唯一索引问题
If column b is also unique, the INSERT is equivalent to this UPDATE statement instead:
If a=1 OR b=2 matches several rows, only one row is updated. In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.
ON DUPLICATE KEY UPDATE c=c+1;
ON DUPLICATE KEY UPDATE c=c+1;
ADD UNIQUE INDEX uniq_b (b ASC);
;
The effects are not quite identical: For an InnoDB table where a is an auto-increment column, the INSERT statement increases the auto-increment value but the UPDATE does not.
If a=1 OR b=2 matches several rows, only one row is updated. In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.
| 涉及到的锁说明
An INSERT … ON DUPLICATE KEY UPDATE on a partitioned table using a storage engine such as MyISAM that employs table-level locks locks any partitions of the table in which a partitioning key column is updated. (This does not occur with tables using storage engines such as InnoDB that employ row-level locking.) For more information, see Section 22.6.4, “Partitioning and Locking”.
Hi,
I am facing this same issue in version 5.7.18. Deadlock error when multiple threads execute INSERT… ON DUPLICATE KEY UPDATE for bulk insert/update.
How it can be fixed?
I am facing the same issue when multiple threads are trying to insert in same table with primary key and unique index. Records are being inserted are different. Also It seems to be taking next-key lock here.
总结
on duplicate key update 在 MyISAM 存储引擎下使用的是表锁,性能不好。
on duplicate key update 在 InnoDB 下并发事务情况下可能会存在锁表/死锁问题。
应尽量避免在多唯一索引的情况下使用此语句。
END
往期精彩程序员缺乏经验的 7 种表现
一款 IDEA 代码防沉迷插件
最新 955 不加班的公司名单
JetBrains 宣布涨价
如何写出令人惊叹的设计文档?
关注后端面试那些事,回复【2022面经】
获取最新大厂Java面经