有业务需求是 如果存在就更新,如果不存在就新增
1、该语句是基于唯一索引或主键使用,需要建立unique index 索引
2、更新操作必须是在已有的数据基础上才会被执行,如果要更新的字段是主键或者唯一索引,不能和表中已有的数据重复,否则插入更新都失败。
3、不管是更新还是增加等操作,都不允许将主键或者唯一索引的字段的数据变成表中已经存在的数据(唯一索引有且只有一个)
使用之后发现ID出现很大的变化,比如一条数据主键id为1,然后第二条就直接是5,这样下去int数据类型估计都撑不住,所以为了解决这样的办法,需要修改innodb_autoinc_lock_mode配置
这个参数控制着在向有auto_increment 列的表插入数据时,相关锁的行为
有0,1,2 这3个级别
分别对应着tradition 、consecutive 、 interleaved
tradition 模式:
1、在这一模式下,所有的insert语句(“insert like”) 都要在语句开始的时候得到一个表级的auto_inc锁,在语句结束的时候才释放这把锁,注意呀,这里说的是语句级而不是事务级的,一个事务可能包涵有一个或多个语句。
2、由于在这种模式下auto_inc锁一直要保持到语句的结束,所以这个就影响到了并发的插入。
consecutive 模式(默认模式):
1、这一模式下去simple insert 做了优化,由于simple insert一次性插入值的个数可以立马得到确定,所以mysql可以一次生成几个连续的值,用于这个insert语句;总的来说这个对复制也是安全的
(它保证了基于语句复制的安全)
2、这一模式也是mysql的默认模式,这个模式的好处是auto_inc锁不要一直保持到语句的结束,只要
语句得到了相应的值后就可以提前释放锁
interleaved 模式:
1、由于这个模式下已经没有了auto_inc锁,所以这个模式下的性能是最好的;但是它也有一个问题,就是对于同一个语句来说它所得到的auto_increment值可能不是连续的。
三种模式简要说明:
0:traditonal (每次都会产生表锁)
1:consecutive (会产生一个轻量锁,simple insert会获得批量的锁,保证连续插入)
2:interleaved (不会锁表,来一个处理一个,并发最高)
由于之前设置的是1,会有一个轻量锁,当执行insert或update,simple insert一次性插入或更新值的个数可以立马得到,当发现insert失败时,对应的id会被抛弃,沿用下一个id用来insert,这时,mysql已经将id记录了,所以就会出现这样的情况,当设置为0时,每次操作得到一个表级的auto_inc锁,有且只能拿到一个id进行操作,当前insert失败时,由于之前的id没有插入成功,所以此id会被回收,mysql继续发放id用来处理剩下的操作
修改自增锁级别方法:
编辑/etc/my.cnf,加入如下行:
innodb_autoinc_lock_mode=0
参考:https://www.jianshu.com/p/10a8d8977aaf