“存在则更新,不存在则插入的逻辑”并发情况下的处理

在sqlserver中:

在sqlserver中,是通过可序列化隔离级别+排它锁的方式来锁定一个范围来实现的
当前锁定一个不存在的记录的时候,sqlserver是通过范围锁来实现的,具体锁定的范围,表中已存在的数据和当前具体判断的Id有关
参考之前写的一篇文章:http://www.cnblogs.com/wy123/p/7501261.html

简单举个例子,如下表中的表中没有任何数据行,Id 字段是primary key

当前Session锁定一个不存在的记录
在另外一个Session中试图锁定相同的记录的时候被阻塞(go提交之后没有任何返回结果,实际上是Session被阻塞)

第一个Session开水器事务

实际上当前Session锁定的范围是从表中的最小值(没有最小值就是无穷小)到无穷大的一个范围
 也就是说说不但锁定了当前Session锁定的Id = 66的数据,甚至只66到正无穷大的数据也被锁定.

以上也即就是sqlserver中范围锁的效果以及适应的场景,可能有其他中写的变种,比如with(serializable),或者with(holdlock),或者先更新再判断受影响行数啥的
本质上都是:序列化隔离级别+事务+排它锁,不但可以锁定已存在的记录行,也可以锁定不存在的记录行。
因此不必纠结各种写法的差异,本质都是一样的。

set transaction isolation level serializable;
begin tran
if exists (select * from TestLockNotExistId with(xlock) where Id = 66)
begin
--更新
update TestLockNotExistId set CreateDate = getdate()
end
else
begin
--插入
insert TestLockNotExistId values (66,'xxx',getdate())
end
commit

在MySQL中:

在MySQL中,是通过insert into values on duplicate key update语法实现的,
虽然MySQL中有类似于SQLServer中显式加锁的语法,也即select from where for update,原本以为可以使用 for update语法来照搬SQL Server的方式实现类似资源隔离
但是经过测试时候,mysql的for update方式显然是锁不住不存在的记录的
但是select from where for update只能锁定已存在的记录,而锁不住不存在的记录

以下测试,无法锁住不存在的记录

可以锁定已存在的记录

因此MySQL中的GAP锁,虽然表面含义也是区间锁(范围锁),与SQLServer中的范围锁,在细节上还是有一定的差异的。
 MySQL在默认的Reapted Read隔离级别下,虽然通过GAP锁解决了幻读的问题,
 但是这种锁仅仅是在读写之间阻塞(互斥)的,在读与读之间,即便是select显式加排它锁的方式,不同Session的同一个不存在Id的查询,也是不阻塞(MySQL的gap锁不阻塞,也就是说两个gap锁,锁定的范围完全一致的时候,如果这个范围内没有数据,则不会互相阻塞)。
 因此无法通过先判断是否存在,再决定是插入或者更新的方式来实现。

20191213补充:

mysql中,对于不存再插入,存在则更新,从sql语句上是无法解决的,经测试,以下Version1和Version2两种写法,并发时均潜在死锁的问题
Version1
  insert into t01 (parameter_key )
  SELECT parameter_key
  WHERE NOT EXISTS
  (SELECT 1 FROM t01 AS t WHERE t.key = parameter_key);
Version2
  insert into t01 (parameter_key )
  SELECT parameter_key
  ON DUPLICATE KEY UPDATE
  lastupdate_date = now()

如下Version3的写法,会给出警告
Version3
  insert IGNORE into t01 (parameter_key )
  SELECT parameter_key

insert ignore与ON DUPLICATE KEY UPDATE是不兼容的,也就是说,MySQL想要达到“存在更新不存在插入的效果”,sql层面是无法解决的

除非显式锁定表,执行插入或者更新语句,最后解锁
#cursor.execute('lock tables t01 WRITE,t01 AS t read;')
cursor.execute(sql_statment)
#cursor.execute('unlock tables;')

https://juejin.im/entry/5adca48df265da0b9c1037c8https://blog.csdn.net/pml18710973036/article/details/78452688http://xiajunhust.github.io/2018/11/30/MySQL%20Insert%20on%20duplicate%E9%94%81/

SQL Server与MySQL在“存在则更新,不存在则插入”并发处理上的一些差异。的更多相关文章

  1. 对Oracle 、SQL Server、MySQL、PostgreSQL数据库优缺点分析

    对Oracle .SQL Server.MySQL.PostgreSQL数据库优缺点分析 Oracle Database Oracle Database,又名Oracle RDBMS,或简称Oracl ...

  2. 从SQL Server到MySQL,近百亿数据量迁移实战

    从SQL Server到MySQL,近百亿数据量迁移实战 狄敬超(3D) 2018-05-29 10:52:48 212 沪江成立于 2001 年,作为较早期的教育学习网站,当时技术选型范围并不大:J ...

  3. sql server vs mysql

    1.中文: my.ini [mysqld] character-set-server=utf8 character-set-client=utf8 data\testdb\db.opt default ...

  4. 通过sql server 连接mysql

    图文:通过sql server 连接mysql   1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/con ...

  5. 数据库 SQL Server 到 MySQL 迁移方法总结

    最近接手一起老项目数据库 SQL Server 到 MySQL 的迁移.因此迁移前进行了一些调查和总结.下面是一些 SQL Server 到 MySQL 的迁移方法. 1. 使用 SQLyog 迁移 ...

  6. atitit。mssql sql server 转换mysql 及 分页sql ast的搭建

    atitit.mssql sql server 转换mysql  及 分页sql ast的搭建 1. 主要的的转换::函数的转换,分页的转换 1 2. 思路::mssql sql >>as ...

  7. SQL Server to MySQL

    使用 Navicat 导入向导迁移 会遇到以下问题 SQL Server 中的 GUID 类型字段会变成 {guid} 多个外层花括号, 导致程序问题. 部分字段类型长度不大一致, 需要手工调整. . ...

  8. Decimal为SQL Server、MySql等数据库的一种数据类型

    Decimal为SQL Server.MySql等数据库的一种数据类型,不属于浮点数类型,可以在定义时划定整数部份以及小数部分的位数.使用精确小数类型不仅能够保证数据计算更为精确,还可以节省储存空间, ...

  9. Linux + .net core 开发升讯威在线客服系统:同时支持 SQL Server 和 MySQL 的实现方法

    前段时间我发表了一系列文章,开始介绍基于 .net core 的在线客服系统开发过程. 有很多朋友一直提出希望能够支持 MySQL 数据库,考虑到已经有朋友在用 SQL Server,我在升级的过程中 ...

随机推荐

  1. 莫烦tensorflow(6)-tensorboard

    import tensorflow as tfimport numpy as np def add_layer(inputs,in_size,out_size,n_layer,activation_f ...

  2. 【Linux常用命令】

    1. ps aux | grep nginx 使用场景:是想查看nginx的打印日志,又不知道nginx的日志路径. ps :是查看进程的命令.使用该命令 可以确定有哪些进程正在运行和运行的状态.进程 ...

  3. 神州数码多区域OSPF配置

    实验要求:掌握多区域OSPF配置 拓扑如下 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface s0/1 进入端口 ip address ...

  4. tomcat升级 遇到的坑

    今天说说tomcat升级后出的问题 以前的版本是8.0.30的 因用安全漏洞 需要升级tomcat 为8.5.28的版本 升级后jvm的配置 等等都和一起一样,过了几天发现,我们的错误日志和处理影响转 ...

  5. 【转载】 Pytorch 细节记录

    原文地址: https://www.cnblogs.com/king-lps/p/8570021.html ---------------------------------------------- ...

  6. .net平台常用组建

    常用的一些开源组件整理: 导出Excel报表的插件:NOPI.dll(基于微软OpenXml实现)开源的作业调度和自动任务框架:Quartz.NET用于大数据搜索引擎的全文检索框架:Lucene.ne ...

  7. linux子系统搭建python3

    我之前win10系统有py3,所以就没有下载,直接输入python ,就会进入python环境,但是,什么包都没有 安装pip $ wget https://bootstrap.pypa.io/get ...

  8. PythonStudy——内存管理之垃圾回收 Memory management Garbage collection

    内存管理 引用计数:垃圾回收机制的依据 # 1.变量的值被引用,该值的引用计数 +1# 2.变量的值被解绑,该值的引用计数 -1# 3.引用计数为0时就会被垃圾回收机制回收 标记清除:解决循环引用问题 ...

  9. JSP本质的理解(浏览器调试,response里面的文本都是out.write写入网络流)

    一.请求转发到一个Servlet 请求重定向后,url显示的是/abc1234这个url 这个jsp页面就是一个servlet[通过our把文本输入的网络流里面去了]

  10. BSS, DATA, TEXT, HEAP, STACK

    BSS, block start segment, static memory, to store the global data which are not initialized. DATA, d ...