上几篇博客我们大致讲了一下mysql的底层结构,什么B+tree,什么Hash需要回行啊,再就是讲了mysql优化的explain,这次我们来说说mysql的锁。

mysql锁

  锁从性能上分为乐观锁(用版本对比来实现)和悲观锁,乐观锁的性能要比悲观锁高。

  从对数据库操作的类型分,分为读锁和写锁(都属于悲观锁)

  读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。除锁以外的线程只可读,不可以写入。

  写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。除锁以外的线程不可以做任何操作。

  从对数据操作的粒度分,分为表锁和行锁,再就是不常提到的间隙锁。

我们主要来说表锁和行锁,还有我们的间隙锁。

注意:有锁等待的几乎都为悲观锁

表锁 

  顾名思义,加了表锁,会将整张表锁住。开销很小,加锁很快,不会出现死锁;锁定粒度大,发生锁冲 突的概率最高,并发度最低;

我们来看几条命令。以student表为例

加表锁:lock table 表名称 read(write),表名称2 read(write);

lock table student write;

查看表状态(是否被加锁):

show open tables;

内有有一个列为In_use为1的即为已有锁存在。

解锁表:unlock tables;

unlock tables;

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁
在执行增删改操作前,会自动给涉及的表加写锁。
1、对MyISAM表的读操作(加读锁) ,不会阻寒其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
2、对MylSAM表的写操作(加写锁) ,会阻塞其他进程对同一表的读和写操作,只有 当写锁释放后,才会执行其它进程的读写操作
3、MylSAM表不支持行锁,也不支持事务。

行锁

  每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。

说到这要提到我们的ACID了,我们来复习一下。

A(atomicity)原子性:

即事务要么全部做完,要么全部不做,不会出现只做一部分的情形,如A给B转帐,不会出现A的钱少了,B的钱却没有增加的情况,要么全部成功,要么全部失败(回滚)。这一系列的动作可以视为一个原子。

C(consistency)一致性:

指的是事务从一个状态到另一个状态是一致的,如A减少了100,B不可能只增加30。

I(isolation)隔离性:

即一个事务在没有完成数据的提交修改时,对其它事务是不可见的。当然这里有个隔离级别的概念,在不同隔离级别下,这里会有不同的表现形式。

D(durability)持久性:

一旦事务提交,则所做修改就会被永久保存到数据库中。

然后就是我们的并发事务处理带来的问题,先过一遍这些都会造成什么后果。

  更新丢失(Lost Update)

当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每 个事务都不知道其他事务的存在,就会发生丢失更新问题–最后的更新覆盖了由其 他事务所做的更新。

举例:比如我们同时开启两个线程去售票,卖一张少一张,我们线程A开启事务,同时我们开启线程B,同时查询到余票为10张,卖一张吧。A卖了一张,10-1,剩余9张,我们B线程也卖了一张也是10-1,也剩余9张,提交A,提交B,我们明明卖了两张票,可是数据库得到的确实9,只卖了一张票。

  脏读(Dirty Reads)

一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数 据就处于不一致的状态;这时,另一个事务也来读取同一条记录,如果不加控 制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提 交的数据依赖关系。这种现象被形象的叫做“脏读”。 一句话:事务A读取到了事务B已经修改但尚未提交的数据,还在这个数据基 础上做了操作。此时,如果B事务回滚,A读取的数据无效,不符合一致性要求。

  不可重读(Non-Repeatable Reads)

一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现 其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不 可重复读”。 一句话:事务A读取到了事务B已经提交的修改数据,不符合隔离性。

  幻读(Phantom Reads)

一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。 一句话:事务A读取到了事务B提交的新增数据,不符合隔离性

后面的两个说完MVCC机制也就知道是怎么回事了,暂时放在这里。

这些问题我们再回到我们的数据库吧。

事务的隔离级别

  

一般都设置为可重复读的。数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。 同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用

对“不可重复读"和“幻读”并不敏感,可能更关心数据并发访问的能力。 常看当前数据库的事务隔离级别: show variables like 'tx_isolation'; 设置事务隔离级别:set tx_isolation='REPEATABLE-READ';

其余的可以自己去尝试一下,读未提交READ-UNCOMMITTED,读已提交READ-COMMITTED,可串行化SERIALIZABLE;

MVCC:

  这个超级重要,懂了这个上面的几乎都懂了~!

英文全称为Multi-Version Concurrency Control,翻译为中文即 多版本并发控制。这个概念很抽象,我们并不知道他控制的是什么。

举一个栗子来说一下,假设我们的MySQL表里有两个虚拟的字段,一个叫开启事务ID,一个叫删除事务ID,都为自增的。再开启事务时不会给予任何数值,在执行第一条SQL时,给予开启事务ID一个数字,我们假设为0,但是不给与提交事务ID(还是为空)。以我们给出的学生表为例上图说话。

简单说一下图的意思,我们每次在运行sql的时候,都会以时间戳生成一个快照版本号,如果是查询SQL,会把这个版本号更新到我们的createID字段,增删改操作会把我们的版本号更新到的deleteID字段,每个线程事务之间版本号是独立的,对于我们的下一次查询来说,我们会查询数据中createID大于等于我们的快照版本号,且deleteID小于我们的当前的快照版本号ID的数据。MVCC一般在可重复读的隔离级别,但同时在读已提交也是试用的。MVCC缺点是会保存多个快照版本,造成了空间的冗余,但是保证了每个线程的独立操作。

间隙锁

简单说一下间隙锁,如果我们的表ID是自增的,我们写一个开启事务,我们写一条修改SQL

update student set name = '1111'  where id>8 and id<22;

也就是说,不管你有没有id为8~22的数据,这时都对小于8的最大ID到大于22的最小ID这个范围加了锁,这断范围是禁止你新增和修改的,其余位置是可以的。看你的表结构

比如你的表是

sql为 update student set name = '1111'  where id>8 and id<22; 其实我们加锁的范围是(6~22)的范围开区间都是不可以操作的 。

 锁升级:

  我们内部的InnoDB的锁是加在索引上的,也就是说,我们update或者delete时后面的where条件尽力要跟索引字段。

锁的分析:

  我们可以通过show status like'innodb_row_lock%';命令来查看我们行锁的争夺情况。

分别表示为

Innodb_row_lock_current_waits: 当前正在等待锁定的数量

Innodb_row_lock_time: 从系统启动到现在锁定总时间长度(等待总时长)

Innodb_row_lock_time_avg: 每次等待所花平均时间(等待平均时长)

Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间

Innodb_row_lock_waits:系统启动后到现在总共等待的次数(等待总次数) 

死锁

也就是相互的锁等待造成死锁。

查看近期死锁日志信息:show engine innodb status\G; 大多数情况mysql可以自动检测死锁并回滚产生死锁的那个事务,但是有些情况mysql没法自动检测死锁

总结

尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁,合理设计索引。

尽量缩小锁的范围,尽可能减少检索条件范围,避免间隙锁。

尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql

尽量放在事务最后执行

尽可能低级别事务隔离

java架构之路-(mysql底层原理)Mysql事务隔离与MVCC的更多相关文章

  1. MySQL事物原理及事务隔离级别

    mysql事物 事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取.事务的正确执行使得数据库从一种状态转换为另一种状态. 事务必须服从ISO/IEC所制定的ACID原则.AC ...

  2. mysql是如何实现事务隔离以及MVCC详解

    提到事务,你肯定会想到ACID(Atomicity.Consistency.Isolation.Durability,即原子性.一致性.隔离性.持久性),我们就来说说其中I,也就是"隔离性& ...

  3. [转帖]java架构之路-(面试篇)JVM虚拟机面试大全

    java架构之路-(面试篇)JVM虚拟机面试大全 https://www.cnblogs.com/cxiaocai/p/11634918.html   下文连接比较多啊,都是我过整理的博客,很多答案都 ...

  4. MySQL数据库引擎、事务隔离级别、锁

    MySQL数据库引擎.事务隔离级别.锁 数据库引擎InnoDB和MyISAM有什么区别 大体区别为: MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是性能 ...

  5. 【原创】互联网项目中mysql应该选什么事务隔离级别

    摘要 企业千万家,靠谱没几家. 社招选错家,亲人两行泪. 祝大家金三银四跳槽顺利! 引言 开始我们的内容,相信大家一定遇到过下面的一个面试场景 面试官:"讲讲mysql有几个事务隔离级别?& ...

  6. 互联网项目中mysql应该选什么事务隔离级别

    引言 开始我们的内容,相信大家一定遇到过下面的一个面试场景 面试官:“讲讲mysql有几个事务隔离级别?” 你:“读未提交,读已提交,可重复读,串行化四个!默认是可重复读” 面试官:“为什么mysql ...

  7. 【转】互联网项目中mysql应该选什么事务隔离级别

    作者:孤独烟 转自:https://www.cnblogs.com/rjzheng/p/10510174.html 摘要 企业千万家,靠谱没几家.社招选错家,亲人两行泪. 祝大家金三银四跳槽顺利! 引 ...

  8. java架构之路-(mysql底层原理)Mysql之让我们再深撸一次mysql

    让我再深撸一次mysql吧,这次主要以应对面试来说说mysql,大概几个方向,索引结构,查询引擎,索引优化,explain的详解和trace工具的使用. 索引: 我们先来看一下mysql的B+tree ...

  9. java架构之路-(面试篇)Mysql面试大全

    说一下mysql比较宏观的面试,具体咋写sql的这里就不过多举例了.后面我还会给出一个关于mysql面试优化的试题,这里主要说的索引和B+Tree结构,很少提到我们的集群配置优化方案. 1.索引是什么 ...

随机推荐

  1. 实战SpringCloud响应式微服务系列教程(第三章)

    接着之前的: 实战SpringCloud响应式微服务系列教程(第一章) 实战SpringCloud响应式微服务系列教程(第二章) 1.1.3Reactor框架 响应式编程是一种编程模型,本节将介绍这种 ...

  2. CRNN+CTC (基于CTPN 的end-to-end OCR)

    1. https://zhuanlan.zhihu.com/p/43534801  (详细原理) 2. https://blog.csdn.net/forest_world/article/detai ...

  3. 9407web常用符号

    常用符号 转载自 http://www.fhdq.net/ ❤❥웃유♋☮✌☏☢☠✔☑♚▲♪✈✞÷↑↓◆◇⊙■□△▽¿─│♥❣♂♀☿Ⓐ✍✉☣☤✘☒♛▼♫⌘☪≍←→◈◎☉★☆⊿※¡━┃♡ღツ☼☁❅♒✎©® ...

  4. Java并发编程知识点总结Volatile、Synchronized、Lock实现原理

    Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...

  5. 如何在Python中表示一个对象

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  6. 【linux】【qt5】【信号槽示例】

    什么叫信号槽: 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal).这种发出是没有目的的, ...

  7. vmware中设置ubuntu静态ip

    概括一下过程中遇到的三个问题: 1.如何修改虚拟机为静态ip并且生效 2.设置完静态ip后,无法上网 3.设置完静态ip且能上网后,宿主机无法ping通虚拟机 问题1:参考https://www.ji ...

  8. lightoj 1057 - Collecting Gold(状压dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1057 题解:看似有点下记忆话搜索但是由于他是能走8个方向的也就是说两点的距离其 ...

  9. 九度 题目1454:Piggy-Bank 完全背包

    题目1454:Piggy-Bank 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:1584 解决:742 题目描述: Before ACM can do anything, a budg ...

  10. Junit测试Controller(MockMVC使用),以及传输@RequestBody数据解决办法

    转自:http://www.importnew.com/21153.html 一.单元测试的目的 简单来说就是在我们增加或者改动一些代码以后对所有逻辑的一个检测,尤其是在我们后期修改后(不论是增加新功 ...