1、脏读

脏页只是在缓冲池中已经修改的页但是没有刷新到磁盘中,即数据库实例内存中的页和磁盘中的页事不一致的,当然在刷新到磁盘之前,日志都已经被写入到了重做日志文件中,而所谓的脏数据是指事务对缓冲池中行记录的修改,但并没有被提交

对于脏页的读取,是非常正常的。脏页是因为数据库实例内存和磁盘异步造成的,这并不影响数据的一致性(或者说两者最终会达到一致性,当脏页刷新回到磁盘中)。并且因为脏页的刷新时异步的,不影响数据库的可用性,带来了性能的提高

脏数据就截然不同,脏数据是未提交的数据,如果读到了脏数据,即一个事务可以读到另一个事务中未提交的数据,则显然违反了数据库的隔离性

脏读是值在不同的事务下,当前事务可以读到另外事务未提交的数据,简单来说就是可以读到脏数据。

表t中的事务隔离级别有默认的RR改成READ UNCOMMITED ,因此在会话A中,在事务未提交的前提下,会话B中的两次SELECT操作取得了不同的结果,并且2这条记录是在会话A中并未提交的数据,即产生了脏读,违反了事务隔离性

脏读隔离看似毫无用处,但在一些比较特殊的情况下还是可以将事务隔离级别设置成READ UNCOMMITTED。例如replication环境中的slave节点,并且该slave的查询不需要特别精确的返回值

2、不可重复读

不可重复读是指在一个事务内多次读取同一数据集合,在这个事务还没有结束时,另外一个事务也访问该同一数据集合,并做了一些DML操作,因此,在第一个事务中两次数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能不一样。这样就发生了在一个事务内两次读到的数据不一样的情况,称为不可重复读

不可重复读和脏读的区别:脏读是读到未提交的数据,而不可重复读读到的是已经提交的数据,但是其违反了数据库一致性的要求

在会话A中开始一个事务,第一次读到的1,另一个会话B中开始另一个事务,插入一条2的记录,在没有提交之前,对会话A中的事务进行再次读取是,读到的记录还是1,没有发生脏读的现象,但在会话B中事务提交后,在会话A中的事务进行读取时,这是读到的是1和2这两条记录,这个例子的前提是,会话A和会话B的事务隔离级别是RC

一般来说,不可重复读是可以接收的,因为其读到的是已经提交的数据,本身不会带来很大的问题,因此很多数据库产商将其事务隔离级别默认设置成RC,在这种隔离级别下允许不可重复读的现象

在InnoDB存储引擎中,通过Next-Key Lock算法来避免不可重复读的问题,在MySQL官方文档将不可重复读的问题定义为Phantom Problem,即幻像问题。在Next-Key Lock算法下,对于索引的扫描,不仅是锁住扫描的索引,还是锁住这些索引覆盖的范围gap,因此这个范围内的插入都是不允许的,这样就避免了另外的事务在这个范围内插入数据导致不可重复读的问题。因此InnoDB存储引擎的默认事务隔离级别是RR,采用Next-Key Lock算法,避免不可重复读的现象

3、丢失更新

丢失更新是另一个锁导致的问题,简单来说其就是一个事务的更新操作会被另一个事务的更新操作锁覆盖,从而导致数据的不一致,例如
事务T1将行记录r更新为v1,但是事务T1并未提交
与此同时,事务T2将行记录r更新为v2,事务T2未提交
事务T1提交
事务T2提交

但是在当前数据库的任何隔离级别下,都不会导致数据库理论上的丢失更新问题。这是因为,即使是READ UNCOMMITTED的事务隔离级别,对于行的DML操作,需要对行或者其他粗粒度级别的对象加锁,因此在上述步骤B中,事务T2并不能对行记录r进行更新操作,其余被阻塞,直到事务T1提交

虽然数据库能阻止丢失更新问题的产生,但是在生产应用中还有另一个逻辑意义的丢失更新问题呢,而导致该问题并不是因为数据库本身的问题。实际上,在所有多用户计算机系统环境下都有可能产生这个问题。简单来说,出现下面的情况,就会发生丢失更新

A.    事务T1查询一行数据,放入本地内存,并显示给一个终端用户User1
B. 事务T2也查询该行数据,并将取得的数据显示给终端用户User2
C. User1修改这行的记录,更新数据库并提交
D. User2修改这行的记录,更新数据库并提交

显然,这个过程中用户User1的修改更新操作会丢失了,而这可能会导致一个恐怖的结果,设想银行发生丢失更新的现象。例如一个用户账号有10 000人民币,他用两个网上银行的客户端分别进行转账操作。第一次转账9000,因为网络和数据的关系,这需要等待,但这是用户操作另一个网上银行客户端,转账1元,如果这两笔操作都成功,用户的余额应该是9999,第一次转的9000并没有得到更新,但是在转账的另一个账户却受到了这9000,这导致的结果是钱变多,而账不平。也许读者会说,不对,我的网银是USB Key的,不会发生这种情况,是的,通过Usb key登录也许可以解决这个问题,但是最重要的是在数据库层解决这个问题,避免任何可能发生更新的情况

要避免丢失更新发生,需要将事务在这种情况下操作变成串行化,而不是并行操作,即在上述步骤的1中,对用户读取的记录加一个排他X锁,同样,在步骤2的操作过程中,用户同样需要加一个排他X锁,通过这种方式,步骤2就必须等待1和步骤3的完成,最后完成步骤4

MySQL中锁问题的更多相关文章

  1. MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

    原文地址:http://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...

  2. MySQL中锁的类型

    InnoDB存储引擎实现了一下两种标准的行级锁: 共享锁S LOCK 允许事务读一行数据 排他锁 X LOCK 允许事务删除或更新一行数据 如果是一个事务T1斤获得了行r的共享锁,那么另外一个事务T2 ...

  3. MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

    悲观锁: 顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁.上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交或者回滚.传统的关 ...

  4. MySql 中锁的定义

    行级锁,一般是指排它锁,即被锁定行不可进行修改,删除,只可以被其他会话select.行级锁之前需要先加表结构共享锁. 表级锁,一般是指表结构共享锁锁,是不可对该表执行DDL操作,但对DML操作都不限制 ...

  5. 【大厂面试05期】说一说你对MySQL中锁的了解?

    这是我总结的一个表格,是本文中涉及到的锁(因为篇幅有限就没有包括自增锁) 加锁范围 名称 用法 数据库级 全局读锁 执行Flush tables with read lock命令各整个库接加一个读锁, ...

  6. mysql的锁与事务

    1. MySQL中的事物 1.InnoDB事务原理 1. 事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态. 2. 在数据库提交 ...

  7. [数据库事务与锁]详解六: MySQL中的共享锁与排他锁

    注明: 本文转载自http://www.hollischuang.com/archives/923 在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大 ...

  8. [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

    注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...

  9. MySQL中select * for update锁表的范围

    MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...

随机推荐

  1. ActiveMQ与MSMQ的异同

    http://www.cnblogs.com/luluping/archive/2010/11/03/1867841.html      目前常用的消息队列组建无非就是MSMQ和ActiveMQ,至于 ...

  2. Easy UI datebox控件无法正常赋值

    <input id="AcceptDetail_IssuingDate" class="easyui-datebox" data-options=&quo ...

  3. 数据库面试题.net

    1.ADO.net中常用的对象 connection, command, sqladapter, dataset, dataview. 2.net中读写数据库要用到哪些类 DataSet数据存储 Da ...

  4. Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)(转)

    转自:http://blog.s135.com/nginx_php_v6/] 前言:本文是我撰写的关于搭建“Nginx + PHP(FastCGI)”Web服务器的第6篇文章.本系列文章作为国内最早详 ...

  5. iOS 提示更新 业务逻辑

    1, 当程序启动,先去APPstore 检查有没有新版本.没有新版本就不提示,有新版本才提示. 2,只有当有提示了,再去判断是强制更新还是普通提示. 3,当后台给返回要强制更新时,就给出提示,并且没有 ...

  6. ModelSim 使用笔记1

    ModelSim 使用笔记1   ModelSim提供了简单仿真方式,还有一种要建立project,目前这种方式暂时够我用了. 总结了以下,做了一个简单的<modelsim quick star ...

  7. UML类图详解_关联关系_多对多

    在关联关系中,很多情况下我们的多重性并不是多对一或者一对多的,而是多对多的. 不过因为我们要考虑里面的导航性,如果直接搞的话就是需要去维护两群对象之间多对多的互指链接,这就十分繁杂且易错.那么我们怎么 ...

  8. 使用pycharm手动搭建python语言django开发环境(三) 使用django的apps应用 添加应用静态文件

    1)在django 工程目录中使用cmd命令行 敲入"python manage.py startapp app名称(例子为blog)" 2)在django工程目录中应该生成了bl ...

  9. WebAssembly,Web的新时代

    在浏览器之争中,Chrome凭借JavaScript的卓越性能取得了市场主导地位,然而由于javascript的无类型特性,导致其运行时消耗大量的性能做为代价,这也是JavaScript的瓶颈之一.W ...

  10. gstreamer 10.5版本发布啦