http://www.2cto.com/database/201408/327940.html 一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边。这两天决定从原理上理解它,整理成自己的知识。查阅资料的过程中发现好多零碎的概念如果串起来足够写一本书,所以在这里给
http://www.2cto.com/database/201408/327940.html
一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边。这两天决定从原理上理解它,整理成自己的知识。查阅资料的过程中发现好多零碎的概念如果串起来足够写一本书,所以在这里给自己梳理一个脉络,具体的内容参考引文或在网上搜一下。由于平时接触最多的是MySQL,所以文章中某些部分是MySQL特有的特性,请读者注意。
数据库并发操作会引发的问题:
多个事务同时访问数据库时候,会发生下列5类问题,包括3类数据读问题(脏读,不可重复读,幻读),2类数据更新问题(第一类丢失更新,第二类丢失更新):脏读(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不会阻塞住数据的查询操作,而是会查询出数据被修改之前的备份,返回给客户端。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中,可以利用char()和REPLACE()函数来替换换行符;REPLACE()函数可以用新字符串替换列中的换行符,而换行符可使用“char(13)”来表示,语法为“replace(字段名,char(13),'新字符串') ”。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于MySQL复制技术的相关问题,包括了异步复制、半同步复制等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了mysql高级篇的一些问题,包括了索引是什么、索引底层实现等等问题,下面一起来看一下,希望对大家有帮助。

在mysql中,是否需要commit取决于存储引擎:1、若是不支持事务的存储引擎,如myisam,则不需要使用commit;2、若是支持事务的存储引擎,如innodb,则需要知道事务是否自动提交,因此需要使用commit。

在mysql中,可利用“ALTER TABLE 表名 DROP INDEX unique key名”语句来删除unique key;ALTER TABLE语句用于对数据进行添加、删除或修改操作,DROP INDEX语句用于表示删除约束操作。

深入理解Linux管道的使用方法在Linux操作系统中,管道是一种非常有用的功能,能够将一个命令的输出作为另一个命令的输入,从而方便地实现各种复杂的数据处理和操作。深入理解Linux管道的使用方法对于系统管理员和开发人员来说非常重要。本文将介绍管道的基本概念,并通过具体的代码示例来展示如何使用Linux管道进行数据处理和操作。1.管道的基本概念在Linux

如何正确理解PHP中的值传递方式PHP是一种广泛应用于Web开发的脚本语言,而在PHP中的参数传递方式主要有值传递和引用传递两种。而理解PHP中的值传递方式对于编写高效的代码至关重要。本文将详细讨论PHP中的值传递方式,并通过具体的代码示例来帮助读者更好地理解。值传递方式的基本概念值传递是指将变量的值复制一份传递给函数或方法,在函数内部对该值的操作不会影响到

深入理解Go语言文档中的strings.Split函数,需要具体代码示例在Go语言中,字符串操作是非常常见的需求。其中,strings包是Go语言提供的一个标准包,提供了丰富的字符串处理函数。其中,strings.Split函数是其中一个常用的函数,它的作用是根据指定的分隔符将一个字符串拆分成一个字符串切片。在正式深入探讨strings.Split函数之前,


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

WebStorm Mac version
Useful JavaScript development tools

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.
