关于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标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
随机推荐
- iot前台开发环境:搭建 SpringBoot+angularJs2
参考网站 Angular 中文官网:https://angular.cn/ 参考代码:https://ng.ant.design/#/components/dropdown npm install ...
- leetcode算法: Average of Levels in Binary Tree
Given a non-empty binary tree, return the average value of the nodes on each level in the form of an ...
- Django ORM那些相关操作
一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/ 官网文档 常用的操作 <1> all() ...
- 通过wget工具下载指定文件中的URLs对应的资源并保存到指定的本地目录中去并进行文件完整性与可靠性校验
创建URLs文件在终端输入cd target_directory回车,便把当前文件夹切换到了目标文件夹target_directory,此后创建的文件都会丢它里面在终端输入cat > URLs回 ...
- SSM登陆注册
package com.coingod.controller; import java.io.IOException;import java.io.PrintWriter;import java.ut ...
- 27.C++- 智能指针
智能指针 在C++库中最重要的类模板之一 智能指针实际上是将指针封装在一个类里,通过对象来管理指针. STL中的智能指针auto_ptr 头文件: <memory> 生命周期结束时,自动摧 ...
- spark2.1:使用df.select(when(a===b,1).otherwise(0))替换(case when a==b then 1 else 0 end)
最近工作中把一些sql.sh脚本执行hive的语句升级为spark2.1版本,其中遇到将case when 替换为scala操作df的方式实现的问题: 代码数据: scala> import o ...
- C#:多进程开发,控制进程数量
正在c#程序优化时,如果多线程效果不佳的情况下,也会使用多进程的方案,如下: System.Threading.Tasks.Task task=System.Threading.Tasks.Task. ...
- Java 局部变量、实例变量、类变量(静态变量)区别
1. 局部变量: 局部变量是类的方法中的变量: 2. 实例变量: 实例变量也是类中独立于方法之外的变量,不过没有static修饰,也叫 对象变量 3. 类变量(静态变量): 类变量是类中独立于方法之外 ...
- hue上配置HA的hdfs文件(注意,HA集群必须这样来配置才能访问hdfs文件系统)
按照正常方式配置,发现无论如何也访问不了hdfs文件系统,因为我们是HA的集群,所以不能按照如下配置 将其改为 除此之外,还需要配置hdfs文件的 接着要去hadoop的目录下启动httpfs.sh ...