mysql RC下不存在则插入
mysql版本:5.7
目的:在RC下,name列上仅有key索引,并发插入name时不出现重复数据
RC不加gap lock,并且复合select语句是不加锁的快照读,导致两个事务同时进行都可插入,测试如下:
client1:
mysql> set tx_isolation='read-committed'; mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec) mysql> create table t (id int primary key, name int, key(name))engine=innodb;
Query OK, 0 rows affected (0.24 sec) ....... mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
+----+------+
7 rows in set (0.00 sec) mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.03 sec) mysql> begin;
Query OK, 0 rows affected (0.00 sec) mysql> insert into t select 8,8 from dual where not exists (select name from t where name=8);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
+----+------+
8 rows in set (0.00 sec)
client2设置同client1,设置略,然后起事务插入:
mysql> begin;
Query OK, 0 rows affected (0.00 sec) mysql> insert into t select 9,8 from dual where not exists (select name from t where name=8);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 9 | 8 |
+----+------+
8 rows in set (0.00 sec)
可以看到并未阻塞,这不同于RR,在RR下会阻塞,因为加了gap lock。
难道这时候没有加任何锁吗,其实并不是,client1执行如下,并查看锁:
mysql> select name from t where name=8 lock in share mode;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from information_schema.innodb_locks;
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| 164163:469:4:10 | 164163 | S | RECORD | `test1`.`t` | name | 469 | 4 | 10 | 8, 9 |
| 164168:469:4:10 | 164168 | X | RECORD | `test1`.`t` | name | 469 | 4 | 10 | 8, 9 |
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
2 rows in set, 1 warning (0.00 sec)
看看加锁的数据。client2如下:
mysql> select name from t where name=8 lock in share mode;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from information_schema.innodb_locks;
+----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| 164168:469:4:9 | 164168 | S | RECORD | `test1`.`t` | name | 469 | 4 | 9 | 8, 8 |
| 164163:469:4:9 | 164163 | X | RECORD | `test1`.`t` | name | 469 | 4 | 9 | 8, 8 |
+----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
2 rows in set, 1 warning (0.00 sec)
看看加锁的数据,可见client1和2都上了锁,是在insert时上的。
那么为了能达到加锁阻塞的目的,可以使用如下方式,client1:
mysql> insert into t select 8,8 from dual where not exists (select name from t where name=8 for update);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
client2则阻塞:
mysql> insert into t select 9,8 from dual where not exists (select name from t where name=8 for update);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from information_schema.innodb_locks;
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| 164170:469:4:10 | 164170 | X | RECORD | `test1`.`t` | name | 469 | 4 | 10 | 8, 8 |
| 164169:469:4:10 | 164169 | X | RECORD | `test1`.`t` | name | 469 | 4 | 10 | 8, 8 |
+-----------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
2 rows in set, 1 warning (0.00 sec)
如果client1在client2阻塞时 commit:
mysql> insert into t select 8,8 from dual where not exists (select name from t where name=8 for update);
Query OK, 1 rows affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> commit;
Query OK, 0 rows affected (0.04 sec)
client2:
mysql> insert into t select 9,8 from dual where not exists (select name from t where name=8 for update);
Query OK, 0 rows affected (4.79 sec)
Records: 0 Duplicates: 0 Warnings: 0
还有一个需要注意的地方是,如果不加for update,则并发插入时,都会插入新数据,client1:
mysql> begin;
Query OK, 0 rows affected (0.00 sec) mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
+----+------+
8 rows in set (0.00 sec) mysql> insert into t select 9,9 from dual where not exists (select name from t where name=9);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
+----+------+
9 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.03 sec) mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | 9 |
+----+------+
10 rows in set (0.00 sec)
与client1并发执行的client2:
mysql> begin;
Query OK, 0 rows affected (0.00 sec) mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
+----+------+
8 rows in set (0.00 sec) mysql> insert into t select 10,9 from dual where not exists (select name from t where name=9);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 10 | 9 |
+----+------+
9 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.04 sec) mysql> select * from t;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | 9 |
+----+------+
10 rows in set (0.00 sec)
可见,根本起不到不存在则插入的效果。
mysql RC下不存在则插入的更多相关文章
- mysql RR下不存在则插入
主要看并发事务中不存在则插入(只有key索引)的阻塞情况. 表定义: mysql> desc user; +-------------+------------------+------+--- ...
- 我的MYSQL学习心得(八) 插入 更新 删除
我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...
- Mysql数据库实践操作之————批量插入数据(100万级别的数据)
第一种方法:使用insert into 插入 从Redis每次获取100条数据,根据条件去插入到Mysql数据库中: 条件: 如果当前队列中的值大于1000条,则会自动的条用该方法,该方法每次获取从队 ...
- mysql三种带事务批量插入
原文:mysql三种带事务批量插入 c#之mysql三种带事务批量插入 前言 对于像我这样的业务程序员开发一些表单内容是家常便饭的事情,说道表单 我们都避免不了多行内容的提交,多行内容保存,自然要用到 ...
- python+mysql:实现一千万条数据插入数据库
作业要求 构建一个关系模式和课本中的关系movies(title,year,length,movietype,studioname,producerC)一样的关系,名称自定,在这个关系中插入1000万 ...
- 如何在mysql客户端即mysql提示符下执行操作系统命令
环境描述: mysql版本:5.5.57-log 操作系统版本:Red Hat Enterprise Linux Server release 6.6 (Santiago) 需求描述: 在mysql的 ...
- 关于mysql安装后在客户端cmd插入语句无法执行的问题
关于mysql安装后在客户端cmd插入语句无法执行的问题 因为windows cmd默认字符集是gbk,当character_set_client=utf8时,cmd中出现中文会报错:characte ...
- Mysql InnoDB下的两种行锁
今天例举2种常见的Mysql InnoDB下的行锁 现有表dr_test(id pk, name) 数据是 1 zhangsan2 lisi3 wangwu 例子1 事务1 update dr_tes ...
- 项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框
JSP mysql SpringMvc下中国省市县三级联动下拉框 关键词 JSP mysql数据库 SpringMvc ajax Controller层 Service层 中国地区 省 ...
随机推荐
- springmvc 孔浩 hibernate
以上为项目文件 用到的jar包:http://pan.baidu.com/s/1kT1Rsqj 1. model-User 2. beans.xml-去哪些包中找annotation:查找相应的实体类 ...
- 【算法34】蓄水池抽样算法 (Reservoir Sampling Algorithm)
蓄水池抽样算法简介 蓄水池抽样算法随机算法的一种,用来从 N 个样本中随机选择 K 个样本,其中 N 非常大(以至于 N 个样本不能同时放入内存)或者 N 是一个未知数.其时间复杂度为 O(N),包含 ...
- Linux SSH无密码登录
Linux服务器常见的登录方式有两种:密码登录.秘钥登录.工作中我们最常使用的是用秘钥登录的方法,因为使用秘钥登录更高效.更安全. 如何实现SSH无密码登录: 原理:无密码ssh登录的主要操作为将本机 ...
- AI_ 视频监控-人体移动捕捉监测
总目录地址:AI 系列 总目录 需要最新源码,或技术提问,请加QQ群:538327407 我的各种github 开源项目和代码:https://github.com/linbin524 需求 为了实现 ...
- [转载]将json字符串转换成json对象
例如: JSON字符串: var str1 = '{ "name": "cxh", "sex": "man" }'; J ...
- 在Windows安装Reids 详解
今天安装了redis,记录点经验 因为Redis项目没有正式支持Windows. 但Microsoft开发和维护一个针对Windows 64版的redis. 下载地址在微软的GitHub上,地址:ht ...
- Linq to SQL 参考Demo
LINQ to SQL语句()之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句 ...
- 关于ubuntu下看视频中文字幕乱码的问题
试了几个播放器都不行.....然后把字幕文件打开后重新保存成utf-8的.... 可以了!!!! 天呐改编码真是一个万能的办法~ 随手记
- 通过修改EIP寄存器实现32位程序的DLL注入
功能:通过修改EIP寄存器实现32位程序的DLL注入 <如果是64位 记得自己对应修改汇编代码部分> 原理:挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器 ...
- docker和定时任务
查看linux信息 cat /etc/issue 以id运行容器docker start 1c3339d7f9a8通过id结束容器 docker kill 1c3339d7f9a8 Ubuntu 安装 ...