插入还是更新
如果有指定的记录就更新,否则插入
1. 传统方法:
if(select) {update} else {insert}
问题:
- if 读 then 写 必然存在并发问题,即使使用事务也无法解决(除非select使用锁定读)
- 至少两次查询,效率低
2. 删除再插入(replace into):
replace into table(id,imei) values(x1,x2)
删除可能违反唯一约束的记录,然后再插入,相当于:
//假设id、imei都有唯一约束delete from table where id = x1delete from table where imei = x2insert into table(id,imei) values(x1,x2)
问题:
使用自增主键的情况下,删插不能和改相提并论,会让与id有关联的其他表产生问题
删+插 ≠ 改
几个唯一约束就有几条delete被执行,效率较差
3. on duplicate key:
insert into table(id,imei) values(x1,x2)on duplicate keyupdate id = x1,imei = x2
我认为 它的执行逻辑应该是 try { insert… } catch(DuplicateKeyException e) { update… }
问题:
update也会使主键增长,这是由于innodb对自增长主键的优化导致的(自增主键使用互斥量而非表锁)
取消此优化可避免这个问题,但是插入会导致整体效率变差
如果id、imei都是唯一约束,id = x1和imei = x2是两条不同的记录时会如何?
数据库两条数据
| id(自增主键) | myid | imei |
|---|---|---|
| 1 | 1 | 456 |
| 2 | 2 | 234 |
insert into table(myid,imei) values(1,234)on duplicate keyupdate myid = 1,imei = 234
结果:
INSERT INTO on_duplicate_key_test VALUES(1,234)on DUPLICATE KEYUPDATE myid = 1,imei = '234'> 1062 - Duplicate entry '234' for key 'imei_index'> 时间: 0.022s
看来on duplicate key只会处理第一个唯一约束的字段,即只是去更新 myid = 1 的记录,然后发现违反了imei的唯一约束,最后返回了失败(Mysql5.7.17)
另外 这种方法不会更改自增主键,除非在on duplicate key update 后指定修改主键
