• Mysql on duplicate key update用法及优缺点


    在实际应用中,经常碰到导入数据的功能,当导入的数据不存在时则进行添加,有修改时则进行更新,

      在刚碰到的时候,一般思路是将其实现分为两块,分别是判断增加,判断更新,后来发现在mysql中有ON DUPLICATE KEY UPDATE一步就可以完成(Mysql独有的语法)。

    ON DUPLICATE KEY UPDATE单个增加更新及批量增加更新的sql

    在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新;如果插入的行数据与现有表中记录的唯一索引或者主键不重复,则执行新纪录插入操作。

    说通俗点就是数据库中存在某个记录时,执行这个语句会更新,而不存在这条记录时,就会插入。

    注意点:

      因为这是个插入语句,所以不能加where条件。

      如果是插入操作,受到影响行的值为1;如果更新操作,受到影响行的值为2;如果更新的数据和已有的数据一样(就相当于没变,所有值保持不变),受到影响的行的值为0。

    该语句是基于唯一索引或主键使用,比如一个字段a被加上了unique index,并且表中已经存在了一条记录值为1,

    下面两个语句会有相同的效果:

    INSERT INTO table (a,b,c) VALUES (1,2,3)  
      ON DUPLICATE KEY UPDATE c=c+1;  
      
    UPDATE table SET c=c+1 WHERE a=1;

    ON DUPLICATE KEY UPDATE后面可以放多个字段,用英文逗号分割。

    再现一个例子:

    INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)  
          ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b); 

    表中将更改(增加或修改)两条记录。

    项目中数据的操作有时候会令人头大,遇到一个需求:

    需要将数据从A数据库的a数据表同步到B数据库的b数据表中(ab表结构相同,但不是主从关系。。。just同步过去)

    第一次同步过去,b表为空,同步很简单。

    但是当a表中的某些数据更新且增加了新数据之后,再想让两个表同步就有些麻烦了。(如果把b表清空,重新同步,数据量过大的话耗费的时间太长,不是一个好办法)

    想着能不能按照时间段来做更新,这段时间内有新数据了,就插入数据,有数据更新了就更新数据。先说下我的思路:

    步骤:

      1.首先我从a表取出某一时间段的数据(分段更新)

      2.往b表内放数据,根据主键判断b表是否已经有此条记录,没有此数据则插入,有了记录则对比数据是否一样,一样则不做更改,不一样就做更新操作。

    此时使用该语句可以满足需要,但是要注意几个问题:

    • 更新的内容中unique key或者primary key最好保证一个,不然不能保证语句执行正确(有任意一个unique key重复就会走更新,当然如果更新的语句中在表中也有重复校验的字段,那么也不会更新成功而导致报错,只有当该条语句没有任何一个unique key重复才会插入新记录);尽量不对存在多个唯一键的table使用该语句,避免可能导致数据错乱。

    • 在有可能有并发事务执行的insert 语句情况下不使用该语句,可能导致产生death lock。

    • 如果数据表id是自动递增的不建议使用该语句;id不连续,如果前面更新的比较多,新增的下一条会相应跳跃的更大。

    • 该语句是mysql独有的语法,如果可能会设计到其他数据库语言跨库要谨慎使用。

    产生death lock原理

    insert ... on duplicate key 在执行时,innodb引擎会先判断插入的行是否产生重复key错误,如果存在,在对该现有的行加上S(共享锁)锁,如果返回该行数据给mysql,然后mysql执行完duplicate后的update操作,然后对该记录加上X(排他锁),最后进行update写入。

    如果有两个事务并发的执行同样的语句,那么就会产生death lock,如:

    赞赏码

    非学,无以致疑;非问,无以广识

  • 相关阅读:
    UINavigationController
    UIWebView
    控制器view的加载顺序initWithNibName >>> viewDidLoad >>> viewWillAppear >>> viewDidAppear
    UITableView
    JS调用OC方法
    【概念】winform的特点
    【概念】指针
    【c++】类的继承(三种继承方式)、基类和派生类、面向对象三要素
    【笔试】C++笔试题
    【c#】解决DataTable.Rows.Add(dr)语句执行速度慢的问题(GridControl)
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15452516.html
Copyright © 2020-2023  润新知