(转)谈谈MySQL的事务隔离级别

这篇文章能够阐述清楚跟数据库相关的四个概念:事务、数据库读现象、隔离级别、锁机制

一、事务

先来看下百度百科对数据库事务的定义:

作为单个逻辑单元执行一系列操作,要么完全执行,要么完全不执行。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

事务有四个属性,称为ACID属性:

1、原子性(Atomicity):事务是一个原子单位,要么全部执行,要么全部不执行。

2、一致性(Consistent):事务的开始和结束,数据都必须保持一致状态。

3、隔离性(isolation):数据库系统提供隔离机制,保证并发事务之间是互相不干扰的。也就意味着事务处理过程中的中间状态对其他的事务是透明的。

4、持久性(Durable):事务完成之后,对数据的修改是永久性的,即使出现系统故障也能够保持。

事务是一系列SQL语句的集合,如果没有事务,会出现什么问题?或者说SQL只能一条一条的单个执行,会出现什么问题?

这个很简单,如果没有事务,我们平时生活中的银行转账就无法操作。

二、数据库读现象

ACID属性里面有一个是隔离级别,即并发事务之间互相不干扰。互相不干扰只是一个终极状态,且需要消耗巨大的性能。在我们实际应用过程中,是存在很大的灰度空间的:隔离级别有程度的区分。所以如果隔离程度控制的比较弱的话,就会产生脏读不可重复读以及幻读的现象。

1、脏读

事务T1修改某个字段的值,然后事务T2读取该值,此后T1撤销了对该字段的更新,或者更新成另外的值才commit到数据库中,这样T2读取的数据是无效的或者错误的。导致T2依据脏数据所做的操作也是错误的。

思聪同学中午去食堂吃饭,看到窗边的座位被如花同学占有了,思聪认为这个座位已经被占有了,就转身去找其他的座位。不料,如花同学起身离开了。事实是:如花并不是吃饭,而是临时坐在那里等她的约会对象,只是临时小坐一会,并没有真正“commit”。

2、不可重复读

在数据库访问中,一个事务范围内的两次相同的查询却返回了不同的数据。

事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行验证而重新读取,却发现得到了不同的结果。

思聪同学中午去食堂吃饭,看到窗边的座位是空的,便屁颠屁颠的跑去打饭,回来后却发现这个座位被如花同学抢去了。

3、幻读

幻读解决了不可重复读的问题,即在同一个事务范围内,两次相同的查询结果是相同的。但是可以新增表中的数据记录。

幻读是指事务T1对表中的数据进行修改,假设修改涉及了表中全部的数据行,同时第二个事务也修改这个表中的数据,这种修改是向表中插入一条新的数据。后面就会出现操作了T1事务的用户发现表中还有没有修改的数据行,仿佛出现了幻觉一样。

思聪同学中午去食堂吃饭,看到窗边的座位是空的,便屁颠屁颠的跑去打饭,回来后窗边的座位还是空的,便很高兴坐上去准备开始吃饭,这时候却发现如花同学搬了一个小板凳坐在旁边狼吞虎咽,思聪顿时没有了胃口。

如果需要解决脏读、不可重复读、幻读等这些数据库读现象,就必须相应提高事务的隔离级别。但是数据库的隔离级别越高,对应的并发能力就越弱,性能也就相应的越差,所以我们还需根据具体的应用场景去权衡。

三、事务隔离级别

1、未提交读

事务的最低隔离级别,在这种隔离级别下,一个事务可以读取另外一个事务未提交的数据。

数据库锁实现原理:

事务T在读数据的时候并未对数据进行加锁,事务T在修改数据的时候对数据增加行级共享锁

T1在读取数据时,T2可以对相同数据进行读取、修改。因为T1没有进行任何锁操作;当T2对记录进行修改时,T1再次读取数据可以读取到T2修改后的数据。因为T2对数据进行修改只增加了行级共享锁,T1可以再增加共享读锁进行数据读取(尽管T2没有提交事务)

如上所述,这种隔离级别,会导致脏读现象

2、已提交读

在一个事务修改数据过程中,如果事务没有进行提交,其他事务不能读取该数据

数据库锁实现原理:

事务T在读取数据时增加行级共享锁,读取一旦结束,立即释放;事务T在修改数据时增加行级排他锁,直到事务结束才释放。

T1在读取数据的过程中,T2也可以对相同数据进行读取,但是不能进行修改(T1增加的是共享锁,T2也可以增加共享锁,但是不能增加排他锁)。T1读取结束后,会立即释放共享锁,这时T2可以增加排他锁,对数据进行修改,而此时T1既不能对数据进行读取也不能进行修改,直到T2事务结束。

如上所述,这种隔离级别,解决了脏读问题,但是不能解决不可重复读现象。

3、可重复读

事务T在数据读取时,必须增加行级共享锁,直到事务结束;事务T在修改数据过程中,必须增加行级排他锁,直到数据结束。

数据库锁实现原理:

T1在读取数据的过程中,T2也可以对相同数据进行读取,但是不能进行修改(T1增加的是共享锁,T2也可以增加共享锁,但是不能增加排他锁)。直到T1事务结束后,才会释放共享锁,这时T2才可以增加排他锁,对数据进行修改。

如上所述,这种隔离级别,解决了不可重复读现象,但是这种隔离级别解决不了幻读的问题:

T1进行查询,读取了10条记录,并对十条记录增加了行级锁,此时T2是无法对这10行数据进行修改操作的,但是由于没有表级锁,它可以增加一条满足T1查询条件的记录。随后T1在进行查询时,会发现虽然10条记录没有改变,但是突然多了一条记录。

4、序列化

产生幻读是由于没有进行范围查询时没有增加范围锁。

数据库锁实现原理:

** 事务T在读取数据时,必须先增加表级共享锁,直到事务结束才释放;事务T在修改数据时,必须先增加表级排他锁,直到事务结束才释放。**

T1在读取A表时,增加了表级共享锁,此时T2也可以读取A表,但是不能进行任何数据的修改,直到T1事务结束。随后T2可以增加对A表的表级排他锁,此时T1不能读取A表中的任何数据,更不能进行修改。

如上所述,可序列化解决了脏读、不可重复读、幻读等读现象,但是隔离级别越来越高的同时,在并发性上也就越来越低。

**四、事务操作实践 **

默认情况下,MYSQL是自动提交的,也就意味着平时我们执行一条update语句时,MYSQL是自动帮我们提交的,尽快我们没有显示执行commit命令。但是这种只适用于单条SQL的执行。

如果我们想要同时执行多条SQL,并且执行过程中有SQL执行异常,需要回滚前面已经成功执行的SQL或者最终想回滚全部,则必须显示的使用事务。

  1. 开始一项事务:start tr ansaction或者begin;

  2. 提交事务:commit;

  3. 回滚事务:rollback;

  4. 事务提交之后的操作:chain;

  5. 事务回滚之后的操作:release;

  6. 修改当前连接的提交方式:set autocommit;如果设置了set autocommit=0,则设置之后所有的事务都需要显式的通过命令来进行提交或者回滚。

查询当前会话的事务隔离级别

images/2pyKrnNwf5pC2F3eBa8A8K3DzBZ2azxA.png

查询当前系统的事务隔离级别

images/DZYPrwHrsK5x5dK4STHQceX2h6iSNDd3.png

修改当前会话的事务隔离级别

images/7Yr4k8krs5naMHn3TciejMjmdxBWRNmH.png

提交读演示

客户端A 开启事务,并更新数据

images/CtxNtjBJCaPHHK3PmxX4xYydWcenNkZY.png

此时事务还没有提交,开启客户端B,并进行查询,此时的数据还是未更新前的

images/2B5FcAmzZ3JWHJs2hX3ZT5WRKDA7DRkN.png

客户端A进行事务提交,然后客户端B查询,此时是最新的数据

images/3ftrb2wN2Yn8Db3AYwBHxd5JmQJsHSap.png

commit and chain的演示

如果在提交的时候使用commit and chain,那么在提交后立即开始一个新的事务

images/R5GMDSkjiZRWx4DmcZ7zQ74TQMn8HKex.png

A提交事务后,B再进行查询

images/3kzdQD32SbywQWxffJBScSWR6wRPxwys.png

开启事务会隐式解锁

锁表期间,用start transaction 命令开始一个新事务,则会隐式的执行unlock tables

A对表进行写锁操作

images/ZKzxAfyfAHfT5Z823rHirYamFRMbhMJQ.png

此时B进行查询:由于被A锁表,所以查询被阻塞

images/yWSc7PWzPSJTNwBBB8D4ZwbCFeYyK5JT.png

A开启一个事务

images/73kdSd5QfJRJa7XtsaH7bkictpYGf3Hm.png

由于A开启事务,隐式的释放了写锁,所以B的查询不再被阻塞

images/5KnEJPYmXTE6TNF2ytyDnf4TspXRmAfr.png

SAVEPOINT的使用

事务中可以通过定义SAVEPOINT,指定回滚事务的一个部分
A开启事务并insert一条记录,并设置savepoint

images/8KnAAhkGr5aH8bh2k28ySfH7PemQZEyc.png

B进行查询,查询到的是开启事务前的数据

images/JyWNj2fPb6iEbbdzcTi6bQr8mBfE6zt8.png

A又插入一条数据,然后回滚到savepoint

images/QsjcpfTa3zy6math65hXSd8hHfE6dbSY.png
images/tfDMCMA4CP4ijB6f7BCd4FN7yhGhtSZY.png

B进行查询

images/tx2tJmcCRzbBf8Pyp5n6NMkSmGyXmBC8.png
作者:冬瓜蔡原文:http://www.cnblogs.com/dongguacai/p/7114885.html
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容