• <dl id='uih4e'></dl>
    <fieldset id='uih4e'></fieldset>

    <i id='uih4e'><div id='uih4e'><ins id='uih4e'></ins></div></i>
      <span id='uih4e'></span>
      <acronym id='uih4e'><em id='uih4e'></em><td id='uih4e'><div id='uih4e'></div></td></acronym><address id='uih4e'><big id='uih4e'><big id='uih4e'></big><legend id='uih4e'></legend></big></address>

      <code id='uih4e'><strong id='uih4e'></strong></code>
      1. <ins id='uih4e'></ins>

        <i id='uih4e'></i>

        1. <tr id='uih4e'><strong id='uih4e'></strong><small id='uih4e'></small><button id='uih4e'></button><li id='uih4e'><noscript id='uih4e'><big id='uih4e'></big><dt id='uih4e'></dt></noscript></li></tr><ol id='uih4e'><table id='uih4e'><blockquote id='uih4e'><tbody id='uih4e'></tbody></blockquote></table></ol><u id='uih4e'></u><kbd id='uih4e'><kbd id='uih4e'></kbd></kbd>

            浅谈MySQL的事务隔离级别-建站运营

            • 时间:
            • 浏览:734


            东京大学SGU申请团队 10年申请经验:https://qic.ac.cn/【微信/QQ:1119261】

            作者:冬瓜蔡来源:https://www.cnblogs.com/dongguacai/p/7114885.html


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

            一、事务

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

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

            事务有四个属性 ,称为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读取结束后  ,会立即释放共享锁