MySQL事务隔离级别

      SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)

       在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)

       这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)

       这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable(可串行化) 
       这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

         这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

         脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

         不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

         幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

         在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:


            脏读:一个事务读取到了另外一个事务没有提交的数据
            事务1:更新一条数据
                             ------------->事务2:读取事务1更新的记录
            事务1:调用commit进行提交
            
            ***此时事务2读取到的数据是保存在数据库内存中的数据,称为脏读。
            ***读到的数据为脏数据
            详细解释:
                脏读就是指:当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,
                另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个
                事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
            
        不可重复读:在同一事务中,两次读取同一数据,得到内容不同
            事务1:查询一条记录
                            -------------->事务2:更新事务1查询的记录
                            -------------->事务2:调用commit进行提交
            事务1:再次查询上次的记录
            
            ***此时事务1对同一数据查询了两次,可得到的内容不同,称为不可重复读
            
        幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同
            事务1:查询表中所有记录
                              -------------->事务2:插入一条记录
                              -------------->事务2:调用commit进行提交
            事务1:再次查询表中所有记录
            
            ***此时事务1两次查询到的记录是不一样的,称为幻读
            详细解释:
                幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,
                这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表
                中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,
                就好象发生了幻觉一样。

      1 脏读:修改时加排他锁,直到事务提交后才释放,读取时加共享锁,读取完释放(并不是直到事务提交才释放)。事务1读取数据时加上共享锁后(这样在事务1读取数据的过程中,其他事务就不会修改该数据),不允许任何事物操作该数据,只能读取,之后1如果有更新操作,那么会转换为排他锁,其他事务更无权参与进来读写,这样就防止了脏读问题。

       但是当事务1读取数据过程中,有可能其他事务也读取了该数据,读取完毕后共享锁释放,此时事务1修改数据,修改完毕提交事务,其他事务再次读取数据时候发现数据不一致,就会出现不可重复读问题,所以这样不能够避免不可重复读问题。

      2 不可重复读:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁读取时候不允许其他事物修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题
      3 幻读问题:采用的是范围锁RangeS RangeS_S模式,锁定检索范围为只读,这样就避免了幻影读问题。

      在使用可序列化事务隔离级别时,对于 Transact-SQL 语句读取的记录集,键范围锁可以隐式保护该记录集中包含的行范围。可序列化隔离级别要求每当在事务期间执行任一查询时,该查询都必须获取相同的行集。键范围锁可防止其他事务插入其键值位于可序列化事务读取的键值范围内的新行,从而确保满足此要求。

      键范围锁可防止幻读。通过保护行之间的键范围,它还可以防止对事务访问的记录集进行幻插入。

      键范围锁放置在索引上,指定开始键值和结束键值。此锁将阻止任何要插入、更新或删除任何带有该范围内的键值的行的尝试,因为这些操作会首先获取索引上的锁。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值