当前位置: 首页 > Linux

MySQL-insertupdatestatementONDUPLICATEKEYUPDATE

时间:2023-04-06 18:46:46 Linux

需求背景在本篇博客《调用ZABBIX的API获取节点主机信息小记》(传送门:https://segmentfault.com/a/11...)本篇博文简单说明如何使用zabbix-api库来获取zabbix监控的各个节点主机信息。获取的信息需要输入数据库。由于节点的数量在不断增加,所以在插入数据库的时候,需要判断节点host是否存在。如果存在则更新各个主机的信息,如果不存在则插入。执行方案首先需要创建表node_status:+------------+------------+------+-----+--------+-------+|领域|类型|空|键|默认|+------------+------+-----+--------+------+|节点名称|变种(100)|否|优先级|空|||知识产权|变种(100)|否||空|||网站|变种(100)|否||空|||frp_num|整数(11)||空|||home_free|大整数(20)|否||空|||内存使用|变种(100)|否||空|||上次|日期时间|否||空||||空||+------------+------------+------+-----+---------+--------+在此表中,将节点主机名node_name设置为PRIMARYKEY。一开始只是想到用if-else语句判断node_name是否存在,存在则更新,不存在则插入。如果不存在(从node_status中选择node_name,其中node_name=target_name)插入node_status(node_name,ip,...)values('target_name','ip',...)否则更新node_statussetip='ip',site='site',...wherenode_name=target_name但是这样写有两个问题:1.效率太差,每次需要执行两条sql语句,一条语句判断node_name是否已经存在于表中,另外一条语句用于插入或更新表中的数据。2.在高并发的情况下,会出现数据问题,无法保证原子性。那么有没有更优雅高效的方法呢?查阅资料后发现MySQL有一条语句很好的解决了这个问题:ONDUPLICATEKEYUPDATE这条语句的语法如下:INSERTINTOtablename(field1,field2,field3,...)VALUES(value1,value2,value3,...)在重复键更新时field1=value1,field2=value2,field3=value3,...;这个语法的目的是为了解决重复,当数据库中有一条记录时,执行这条语句会更新它,如果这条记录不存在,则插入。语句规则如下:如果你插入的记录导致UNIQUE索引或主键(primarykey)重复出现,则认为该记录存在,执行update语句而不是insert语句.否则,将执行插入语句而不是更新语句。陈述。得到这条insert语句的“八倍镜像”后,我们可以替换原来很LOW的方法:sql="""INSERTINTOnode_status(node_name,ip,site,frp_num,\+home_free,mem_use,last_time,modify_time)\+VALUES('%s','%s','%s','%d','%d','%s','%s','%s')\+重复密钥更新\+ip='%s',site='%s',frp_num='%d',home_free='%d',\+mem_use='%s',last_time='%s',modify_time='%s'"""%\+(id_value['host'],ip,site,frp_num,home_size,mem_use,last_time,modify_time),+(ip,site,frp_num,home_size,mem_use,last_time,modify_time)参考资料1,https://blog.csdn.net/analogo...2、https://blog.csdn.net/woshiha...