MySQL:插入更新語句ON DUPLICATE KEY UPDATE

需求背景

在《調用ZABBIX的API獲取節點主機信息小記》(傳送門:https://segmentfault.com/a/11...)這篇博客中,簡單闡述瞭如何利用zabbix-api庫來獲取ZABBIX監控各節點主機的信息。須要將獲取的信息錄入數據庫,因爲節點數目不斷增長,所以插入數據庫時,要判斷節點主機是否存在,存在則更新各主機信息,不存在則插入。node

實現方案

首先須要創建一張表node_status:sql

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| node_name    | varchar(100) | NO   | PRI | NULL    |       |
| ip           | varchar(100) | NO   |     | NULL    |       |
| site         | varchar(100) | NO   |     | NULL    |       |
| frp_num      | int(11)      | NO   |     | NULL    |       |
| home_free    | bigint(20)   | NO   |     | NULL    |       |
| mem_use      | varchar(100) | NO   |     | NULL    |       |
| last_time    | datetime     | NO   |     | NULL    |       |
| modify_time  | datetime     | NO   |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

該表中,將node_name即節點主機名稱設爲PRIMARY KEY。數據庫

一開始只是想到了用 if-else語句,判斷node_name是否存在,存在則更新,不存在則插入。segmentfault

if not exists (select node_name from node_status where node_name = target_name)
      insert into node_status(node_name,ip,...) values('target_name','ip',...)
else
      update node_status set ip = 'ip',site = 'site',... where node_name = target_name

可是這麼寫出來,出現了兩個問題:
一、效率太差,每次都須要執行兩條SQL語句,一條語句用來判斷node_name是否在表中已經存在,另外一條語句用來插入或更新表中數據。
二、高併發的狀況下數據會出問題,不能保證原子性。api

那麼有沒有更優雅高效的方法呢,經過查閱資料,發現MySQL一條語句很好的解決了這個問題:ON DUPLICATE KEY UPDATE
該語句的語法以下:併發

INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ON DUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, ...;

這個語法的目的是爲了解決重複性,當數據庫中存在某個記錄時,執行這條語句會更新它,而不存在這條記錄時,會插入它。
該語句規則以下:若是你插入的記錄致使一個UNIQUE索引或者primary key(主鍵)出現重複,那麼就會認爲該條記錄存在,則執行update語句而不是insert語句,反之,則執行insert語句而不是更新語句
獲得了這個插入語句的」八倍鏡「,咱們能夠將原來那個很LOW的方式替換掉了:高併發

sql = """ INSERT INTO node_status(node_name,ip,site,frp_num, \
+                        home_free,mem_use,last_time,modify_time) \
+                        VALUES('%s','%s','%s','%d','%d','%s','%s','%s') \
+                        ON DUPLICATE KEY UPDATE  \
+                        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)

參考資料

一、https://blog.csdn.net/analogo...
二、https://blog.csdn.net/woshiha....net

相關文章
相關標籤/搜索