理解MySql事务隔离机制、锁以及各种锁协议
一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边。这两天决定从原理上理解它,整理成自己的知识。查阅资料的过程中发现好多零碎的概念假设串起来足够写一本书,所以在这里给自己梳理一个脉络,详细的内容參考引文或在网上搜一下。因为平时接触最多的是MySQL。所以文章中某些部分是MySQL特有的特性,请读者注意。
数据库并发操作会引发的问题:
- 脏读(dirty read):A事务读取B事务尚未提交的更改数据。并在这个数据基础上操作。
假设B事务回滚,那么A事务读到的数据根本不是合法的。称为脏读。
在oracle中,因为有version控制,不会出现脏读。
- 不可反复读(unrepeatable read):A事务读取了B事务已经提交的更改(或删除)数据。比方A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。
- 幻读(phantom read):A事务读取了B事务已经提交的新增数据。注意和不可反复读的差别。这里是新增,不可反复读是更改(或删除)。这两种情况对策是不一样的,对于不可反复读,仅仅须要採取行级锁防止该记录数据被更改或删除。然而对于幻读必须加表级锁。防止在这个表中新增一条数据。
- 第一类丢失更新:A事务撤销时。把已提交的B事务的数据覆盖掉。
- 第二类丢失更新:A事务提交时,把已提交的B事务的数据覆盖掉。
数据库在并发操作下会出现上述这些问题,要解决它就要想办法在运行可能引发问题的操作之前将该操作堵塞住,让它等到合适的时机再运行。
那么怎样挑选合适的时机堵塞操作的运行。又怎样保证在调度过程运行完毕后其运行结果与串行运行操作的结果同样呢?
三级封锁协议
数据库想要在“合适”的时机堵塞住数据库操作,那么首先要定义好怎么样的时机算是“合适”,由于各个系统支持的业务千差万别,对数据的实时性和有效性的要求也不同。
于是数据库理论中就提出了封锁级别的概念,对不同的同步要求採用不同的封锁级别。
三级封锁协议内容例如以下:
- 一级封锁协议:事务T在改动数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包含正常结束(COMMIT)和非正常结束(ROLLBACK)。
一级封锁协议能够防止丢失改动,并保证事务T是可恢复的。使用一级封锁协议能够解决丢失改动问题。在一级封锁协议中。假设不过读数据不正确其进行改动。是不须要加锁的,它不能保证可反复读和不读“脏”数据。
- 二级封锁协议:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁。读完后方可释放S锁。
二级封锁协议除防止了丢失改动,还能够进一步防止读“脏”数据。但在二级封锁协议中,因为读完数据后就可以释放S锁,所以它不能保证可反复读。
- 三级封锁协议 :一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。
三级封锁协议除防止了丢失改动和不读“脏”数据外,还进一步防止了不可反复读。
事务隔离级别:
三级封锁协议反映在实际的数据库系统上。就是四级事务隔离机制。
总的来说,四种事务隔离机制就是在逐渐的限制事务的自由度,以满足对不同并发控制程度的要求。下面就是数据库的四种隔离级别:
Read Uncommitted、Read Committed、Repeatable Read、Serializable
其对各个并发问题的制约强度见下表:
√: 可能出现 ×: 不会出现
脏读 | 不可反复读 | 幻读 | |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
四种级别对并发问题的解决由弱到强。对应的系统性能由强到弱,MySQL的默认级别是Repeatable Read。
Read Uncommitted
在Read Uncommitted策略下,数据库遵循一级封锁协议,仅仅对改动数据的并发操作做限制。一个事务不能改动其它事务正在改动的数据,但能够读取到其它事务中尚未提交的改动,这些改动假设未被提交。将会成为脏数据。
Read committed
在Read committed策略下,数据库遵循二级封锁协议。仅仅同意读取已经被提交的数据,反过来讲,假设一个事务改动了某行数据且尚未提交。而第二个事务要读取这行数据的话,那么是不同意的。
在MySql的InnoDB下,尽管这样的操作不被同意。但MySQL不会堵塞住数据的查询操作,而是会查询出数据被改动之前的备份。返回给client。MySQL的这样的机制称为MVCC(多版本号并发控制),就是说数据库在事务并发的过程中对数据维护多个版本号,使得不同的事务对不同的数据版本号进行读写(MVCC的实现參见引用中的文章)。这样的机制反映在应用中就是,在不论什么时候对数据库查询总是能够得到数据库中近期提交的数据。为被提交的脏数据被隔离起来,无法被查询到,即防止脏读发生。
Repeat Read
Repeat Read又比Read Committed更加严格一点。但仍然是在二级封锁协议的范畴,仅仅是读取过程受到很多其它MVCC的影响。在Read Committed下,同意一个事务中多次同样查询得到不同的结果,就是所谓的不可反复读问题。这在一些应用中是同意的。所以oracle、SQL server上默认这一隔离级别。但MySQL没有。它默认Repeat Read级别。在这一级别下,有赖于MVCC,同一个事务中的查询仅仅能查到版本号号不高于当前事务版本号的数据,即事务仅仅能看到该事务開始前或者被该事物影响的数据。反过来说。这一级别下,不同意事务读取在该事务開始后新提交的数据。即防止了不可反复读的发生。
依靠上面的机制,已经做到了在事务内数据内容的不变,可是不能保证多次查询得到的数据数量一致。由于在一个事务运行的过程中别的事务全然能够运行数据插入。当插入了刚好符合查询条件的数据时,就会引发数据查询结果集添加。引发幻读。
另一种情况就是。假设一个事务想插入一条数据,而另一个事务已经插入了含有同样主键的数据,那么当前事务也会被堵塞,并终于运行失败,尽管当前事务根本无法查询到这一条数据,这也是一种幻读。
InnoDB提供的间隙锁机制能够在一定程度上防止幻读的发生。详细介绍见最后一篇引文。
Serializable
最后,最强事务隔离机制Serializable,它遵循三级封锁协议,使得全部的事务必须串行化运行,仅仅要有事务在对表进行查询,那么在此事务提交前,不论什么其它事务的改动都会被堵塞。这攻克了一切并发问题。但会造成大量的等待、堵塞甚至死锁。使系统性能减少。
要注意,在不论什么一种隔离机制下,都是不同意一个事务删除或改动还有一个事务影响过而未提交的数据的。由于事务增、删、改数据以后,会在该行加上排它锁,排它锁会堵塞其它事务再次对该行数据操作。也正是由于排它锁的存在,这四种隔离机制都不会出现不论什么一种更新丢失的现象,由于一条信息根本不同意第二个事务进行改动。
两段锁协议
数据库在调度并发事务时遵循“两段锁”协议,“两段锁”协议是指全部事务必须分两个阶段对数据项进行加锁和解锁
- 扩展阶段:在对不论什么数据项的读、写之前,要申请并获得该数据项的封锁。
- 收缩阶段:每一个事务中,全部的封锁请求必须先于解锁请求。
在数学上能够证明。遵循两段锁的调度能够保证调度结果与串行化调度同样。
这种机制保证了数据库并发调度与串行调度的等价。
*注:
參考资料:
http://blog.csdn.net/fg2006/article/details/6937413
http://blog.csdn.net/chen77716/article/details/6742128
http://www.2cto.com/database/201304/201415.html
http://snailxr.iteye.com/blog/1143615
http://blog.sina.com.cn/s/blog_711b11fd0101bhks.html
http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html
转载请注明出处:
理解MySql事务隔离机制、锁以及各种锁协议的更多相关文章
- 五分钟后,你将真正理解MySQL事务隔离级别!
什么是事务? 事务是一组原子性的SQL操作,所有操作必须全部成功完成,如果其中有任何一个操作因为崩溃或其他原因无法执行,那么所有的操作都不会被执行.也就是说,事务内的操作,要么全部执行成功,要么全部执 ...
- [MySQL数据库之事务、读现象、数据库锁机制、多版本控制MVCC、事务隔离机制]
[MySQL数据库之事务.读现象.数据库锁机制.多版本控制MVCC.事务隔离机制] 事务 1.什么是事务: 事务(Transaction),顾名思义就是要做的或所做的事情,数据库事务指的则是作为单个逻 ...
- 详解Mysql事务隔离级别与锁机制
一.概述 我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能 就会导致我们说的脏写. 胀读和不可重复读.幻读这些问题. 这些问题的本质都是数据库的多事务并 ...
- 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
- 第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景
在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种 ...
- 查询mysql事务隔离级别
查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离 ...
- 轻松理解MYSQL MVCC 实现机制
轻松理解MYSQL MVCC 实现机制 转载https://blog.csdn.net/whoamiyang/article/details/51901888 1. MVCC简介 1.1 什么是MVC ...
- Mysql事务-隔离级别
MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...
- [51CTO]新说MySQL事务隔离级别!
新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...
随机推荐
- Shape,expand_dims,slice基本用法
import tensorflow as tf t = tf.constant([[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]], [[5, 5, 5], ...
- 错误处理: Python值传递和引用传递的问题
1.插入数据库的时候报错110, 提示columns数量少于插入的值内容. 2.核对了下栏目并没有少,打印出插入的值,看看值是不是多了. 查看了下,确实第二次值的时候长度边长了,第二次把第一次的部分值 ...
- 再谈 Go 语言在前端的应用前景
12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...
- 【bzoj2339】[HNOI2011]卡农 dp+容斥原理
题目描述 题解 dp+容斥原理 先考虑有序数列的个数,然后除以$m!$即为集合的个数. 设$f[i]$表示选出$i$个集合作为满足条件的有序数列的方案数. 直接求$f[i]$较为困难,考虑容斥,满足条 ...
- 解决ul的li横向排列换行的问题
1. 问题现象 先看下面的html结构: <div> <ul> <li><img src='./img/1.jpg'></li> <l ...
- ACM程序设计选修课——1030: Hungar的时尚球场(水题+耐心)
1030: Hungar的时尚球场 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 14 Solved: 8 [Submit][Status][Web ...
- [POI2007]MEG-Megalopolis (树状数组,Dfs序)
题目描述 Solution 这道题考试的时候竟然没有仔细想,结果只拿了暴力分... 其实就是一个 DFS序+树状数组. 我们先把用 DFS 把它变成一个序列,同时记录它们的 \(siz\). 那么我们 ...
- python基于SQLAlchemy的DBtools
新版,只创建一次线程池 # -*- coding: utf-8 -*- from sqlalchemy import create_engine from sqlalchemy.orm import ...
- pytesseract的使用
首先,先安装好Tesseract软件,pytesseract模块 问题 1 :FileNotFoundError: [WinError 2] 系统找不到指定的文件. 加上这行代码 pytesserac ...
- 开源 project
移动:http://www.csdn.net/article/2014-04-22/2819435-facebook-mobile-open-source-projects/1