建立一張表node_status:
+--------------+--------------+------+-----+---------+-------+
| 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 語句,判斷主鍵是否存在,存在則更新,不存在則插入。
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
但是這麼寫出來,出現了兩個問題:
1、效率太差,每次都需要執行兩條SQL語句,一條語句用來判斷node_name是否在表中已經存在,另一條語句用來插入或更新表中數據。
2、高併發的情況下數據會出問題,不能保證原子性。
那麼有沒有更優雅高效的方法呢,通過查閱資料,發現MySQL一條語句很好的解決了這個問題:ON DUPLICATE KEY UPDATE
該語句的語法如下:
INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ONDUPLICATE 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)