关于InnoDB的读写锁类型以及加锁方式
(本文为了方便,英文关键词都都采用小写方式,相关知识点会简单介绍,争取做到可以独立阅读)
文章开始我会先介绍本文需要的知识点如下:
- innodb的聚簇索引(聚集索引)和非聚簇索引(二级索引、非聚集索引)的知识
- innodb的隔离级别(isolation level)
- 简单的sql知识(能读懂sql语句)
- MVCC(Multi-Version Concurrent Control)多版本并发控制
- 数据的脏读、幻读(如果有时间会详细讲一下脏读如果没时间,网上讲这个地方的也很多)
问题1:读有几种模式、加锁有几种方式
1. select * from my_table where id = 1;
2. select * from my_table where id = 1 lock in share mode;
3. select * from my_table where id = 1 for update;
4. update my_table set address = 'tianjin' where id = 1;
读的模式分为两种:
- 快照读(snapshot read)
- 当前读(current read)
加锁的方式:(未涉及意向锁)
update my_table set name ='zhang' where id = 1;
假设id为主键:此条sql执行的时候会给此行数据加x锁,如下图
1. select * from my_table where id = 1;
2. select * from my_table where id = 1 lock in share mode;
我们上面说过,语句1为快照读,对其他的读或者写没有影响。所以这两条语句并行时,1读快照,2为语句加s锁。
select * from my_table where id = 1 lock in share mode;
2. select * from my_table where id = 1 lock in share mode;
3. select * from my_table where id = 1 for update;
其中语句2加s锁,3加x锁(在数据被加s锁的时候,其他的给这条想要读取这条记录也需要给这条记录加s锁,这就是为什么s锁是共享锁。此时是不允许再给这条记录加x锁的)两种锁是不能同时存在在一条记录上的。所以两条语句不能并发执行。
3. select * from my_table where id = 1 for update;
4. update my_table set address = 'tianjin' where id = 1;
下面我们来讨论一下id不为主键的情况
- 二级唯一索引
- 二级不唯一索引
- 没有索引
4. update my_table set address = 'tianjin' where id = 1;
这个时候我们需要对索引知识有一定的了解,上面说过二级索引中的叶子节点存储的除了索引信息还有到实际数据的逻辑指针,也就是说我们需要现在二级唯一索引中查找到这条记录的逻辑指针,然后通过指针去查找到数据实际的存储位置并给这条数据加锁。注意,这里的加锁应该是加在了索引上和数据本身上(或者说是聚簇索引上也可以,因为两者是存储在一个结构中的,而innodb中二级索引叶子中的逻辑指针并不是数据存储的物理地址,而是主键值)而不只是二级唯一索引上。如果想用好innodb,他的索引结构是必须要学习的,如果以后有时间会详细介绍。
5. update my_table set address = 'tianjin' where age = 25;
此种情况比前一种情况更特殊,因为情况3和4都只能找到一条记录,只需要对这条记录加锁,则不会发生结果集被修改的情况。但是如果age为二级非唯一索引,我们看到如下表格中有两条记录age=25
update my_table set age=25 where id=2;
则发生幻读现象。gap锁可以防止在语句或者事务执行过程中有满足条件的记录插入进来造成幻读。所以说在此种情况下,除了给满足条件的二级索引和数据(或聚簇索引)加x锁之外还要给相关的间隙加锁。可以理解为这个加gap锁是在二级索引的范围内防止新的索引项加入,因为二级索引本身也是有序的。
5. update my_table set address = 'tianjin' where age = 25;
关于InnoDB的读写锁类型以及加锁方式的更多相关文章
- Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁
相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...
- pthread中读写锁
读写锁很像一个互斥量,他阻止多个线程同时修改共享数据的另一种方法,区分不同互斥量的是他是分读数据和写数据,一个读写锁允许同时多个线程读数据,只要他们不修改数据. 只要没有写模式下的加锁,任意线程都可以 ...
- C基础 读写锁中级剖析
引言 读写锁 是为了 解决, 大量 ''读'' 和 少量 ''写'' 的业务而设计的. 读写锁有3个特征: 1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞 2.当 ...
- Linux 自旋锁,互斥量(互斥锁),读写锁
自旋锁(Spin Lock) 自旋锁类似于互斥量,不过自旋锁不是通过休眠阻塞进程,而是在取得锁之前一直处于忙等待的阻塞状态.这个忙等的阻塞状态,也叫做自旋. 自旋锁通常作为底层原语实现其他类型的锁. ...
- 嵌入式 Linux线程同步读写锁rwlock示例
读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁.1. 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞:2. ...
- Linux的线程同步对象:互斥量Mutex,读写锁,条件变量
进程是Linux资源分配的对象,Linux会为进程分配虚拟内存(4G)和文件句柄等 资源,是一个静态的概念.线程是CPU调度的对象,是一个动态的概念.一个进程之中至少包含有一个或者多个线程.这 ...
- Java 并发包中的读写锁及其实现分析
1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...
- linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客
linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客 linux中读写锁的rwlock介绍 2013-02-26 13:59:35 分类: C/C++ http://yaro ...
- UNIX环境高级编程——线程同步之读写锁以及属性
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
随机推荐
- nyoj 复杂度
复杂度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) for(k=j+1;k ...
- OO第一次总结
第一次作业: 第一次作业的指导书发下来之后我按着上面的步骤一步一步的做了之后发现项目拉下来了,怎么开始码代码呢...然后在舍友的帮助下才知道怎么建包建类,然后对Java的语法又不是很了解,于是就先把C ...
- 数据结构-线性表的链式存储相关算法(C语言实现)
链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...
- 第三章 JavaScript操作BOM对象
第三章 JavaScript操作BOM对象 一.window对象 浏览器对象模型(BOM)是javascript的组成之一,它提供了独立与浏览器窗口进行交换的对象,使用浏览器对象模型可以实现与HT ...
- 搭建一个web服务下载HDFS的文件
需求描述 为了能方便快速的获取HDFS中的文件,简单的搭建一个web服务提供下载很方便快速,而且在web服务器端不留临时文件,只做stream中转,效率相当高! 使用的框架是SpringMVC+HDF ...
- Zepto.js库touch模块代码解析
Zepto.js也许并不陌生,专门针对移动端开发,Zepto有一些基本的触摸事件可以用来做触摸屏交互(tap事件.swipe事件),Zepto是不支持IE浏览器的. 下面来解析一些Zepto.js触摸 ...
- Swagger: 一个restful接口文档在线生成+功能测试软件
一.什么是 Swagger? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 ...
- python入门(7)Python程序的风格
python入门(7)Python程序的风格 Python采用缩进方式,写出来的代码就像下面的样子: # print absolute value of an integer: a = 100 if ...
- [转]安卓新一代多渠道打包工具Walle 解决渠道包V2签名问题
转自https://www.jianshu.com/p/572b59829a08 为什么要打多个渠道的包? 大家都知道,android应用商店大大小小有几百个,作为一个有志向的app,就需要做到统计各 ...
- zipline-benchmarks.py文件改写
改写原因:在这个模块中的 get_benchmark_returns() 方法回去谷歌财经下载对应SPY(类似于上证指数)的数据,但是Google上下载的数据在最后写入Io操作的时候会报一个恶心的编码 ...