追踪着鹿的猎人是看不见山的

0%

mysql优化on DUPLICATE key Update

场景

有张表,里面的记录不能存在重复记录,记录存在就更新,如果不存在就插入,分布式并发场景下会存在以下问题:

1
 Duplicate entry '1203923435854168066-139-68' for key 'PRIMARY'

  • 解决方案
  • DUPLICATE key Update(本文重点)
  • 分布式锁

  • 传统做法

两条sql语句,对于大并发来说,存在性能问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 插入或更新数据
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int insertOrUpdate(Connection conn, Entity record, String... keys) {
final Entity where = record.filter(keys);
if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) {
return update(conn, record, where);
} else {
return insert(conn, record);
}
}

优化方法

创建表,注意要有一个唯一索引 new_code_index, 插入或者更新时,以此为标准

1
2
3
4
5
6
7
8
9
10
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`a` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`b` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`c` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `new_code_index` (`c`) USING BTREE
);

sql语句实例

第一次

1
2
3
4
5
INSERT INTO test ( a, b, c, update_time, create_time ) VALUES ( 'aaaa', 'bbb', MD5(CONCAT('qwewq', 'qweqw')), NOW(), NOW() ) 
ON DUPLICATE KEY UPDATE update_time = now(), create_time = now();

受影响的行: 1
时间: 0.005s

第二次

1
2
3
4
5
INSERT INTO test ( a, b, c, update_time, create_time ) VALUES ( 'aaaa', 'bbb', MD5(CONCAT('qwewq', 'qweqw')), NOW(), NOW() ) 
ON DUPLICATE KEY UPDATE update_time = now(), create_time = now();

受影响的行: 2
时间: 0.005s
坚持原创技术分享,您的支持将鼓励我继续创作!