hsyhado123
hsyhado123
采纳率100%
2015-01-21 03:55 阅读 4.1k

mysql 事务控制 新增后修改

如题:
现在想寻求一个解决方案:
第一步:开启事务控制,
第二步:新增一条数据,
第三步:对新增的数据进行修改,
第四步:事务提交或者回滚。

请问有什么好的解决方案吗?谢谢

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

4条回答 默认 最新

  • 已采纳
    lzp_lrp WorldMobile 2015-01-21 04:34

    理解MySql事务隔离机制、锁以及各种锁协议

    mysql事务隔离三级封锁两段锁MCVV
    一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边。这两天决定从原理上理解它,整理成自己的知识。查阅资料的过程中发现好多零碎的概念如果串起来足够写一本书,所以在这里给自己梳理一个脉络,具体的内容参考引文或在网上搜一下。由于平时接触最多的是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,它遵循三级封锁协议,使得所有的事务必须串行化执行,只要有事务在对表进行查询,那么在此事务提交前,任何其他事务的修改都会被阻塞。这解决了一切并发问题,但会造成大量的等待、阻塞甚至死锁,使系统性能降低。

    要注意,在任何一种隔离机制下,都是不允许一个事务删除或修改另一个事务影响过而未提交的数据的。因为事务增、删、改数据以后,会在该行加上排它锁,排它锁会阻塞其他事务再次对该行数据操作。也正是由于排它锁的存在,这四种隔离机制都不会出现任何一种更新丢失的现象,因为一条信息根本不允许第二个事务进行修改。
    

    两段锁协议
    数据库在调度并发事务时遵循“两段锁”协议,“两段锁”协议是指所有事务必须分两个阶段对数据项进行加锁和解锁
    扩展阶段:在对任何数据项的读、写之前,要申请并获得该数据项的封锁。
    收缩阶段:每个事务中,所有的封锁请求必须先于解锁请求。
    在数学上可以证明,遵循两段锁的调度可以保证调度结果与串行化调度相同。这样的机制保证了数据库并发调度与串行调度的等价。

    点赞 1 评论 复制链接分享
  • lzp_lrp WorldMobile 2015-01-21 04:34

    基于MySQL的分布式事务的应用和缺陷

    摘要:MySQL从5.0.3版本就开始支持分布式事务,并且只有InnoDB存储引擎支持分布式事务。一个分布式事务涉及到多个事务性的活动,这些活动都必须一起完成或者一起被回滚。然而MySQL的分布式事务技术还在建设中,存在一定的漏洞。本文介绍MySQL在分布式事务中的应用并对其漏洞进行浅析。
    中国论文网 http://www.xzbu.com/8/view-44494.htm
       关键词:分布式事务;数据库;MySQL
       中图分类号:TP311.13 文献标识码:A 文章编号:1007-9599 (2011) 23-0000-01
       MySQL-based Applications and Defects of Distributed Affairs
       Men Wei
       (China University of Mining&Technology,School of Computer Science&Technology,Xuzhou 221116,China)
       Abstract:Distributed Transaction has been supported by MySQL since the 5.0.3 version,and It is only be supported by InnoDB storage engine.A distributed transaction is referred to many transactional activities,and these activities must be finished together,otherwise,they will be rolled back together.However,the technology of Distributed Transaction in MySQL is under construction and it has also some bug.This paper will introduce the use of Distributed Transaction in MySQL and analyse the bugs simply.
       Keywords:Distributed Affairs;Database;MySQL
      一、分布式事务概述
      (一)分布式事务的概念和用途
       分布式事务的事务参与者、资源管理器、事务管理器等位于不同的节点上,这些不同的节点相互协作共同完成一个具有逻辑完整性的事务。本文主要介绍的是MySQL在分布式事务中的应用与漏洞分析。
       分布式事务的主要作用在于确保事务的一致性和完整性。它利用分布式的计算环境,在TP系统的支持下,将多个事务性的活动合并成一个事务单元,这些事务性的活动要么一起执行,要么都不执行,从而保证了多个活动之间的一致性和完整性。
       (二)分布式事务的相关概念
       1.资源管理器(Resource Manager):资源管理器管理系统资源,是通向事务资源的途径。数据库就是一种资源管理器。资源管理还应该具有管理事务提交或回滚的能力。
       2.事务管理器(Transaction Manager):事务管理器是分布式事务的核心管理者。事务管理与每个RM进行通信,协调并完成事务的处理。事务的各个分支是由某种命名方法进行标识。
       二、MySQL中分布式事务模型对照和执行过程分析
       MySQL在执行分布式事务(XA MySQL)的时候,MySQL服务器相当于XA事务资源管理器,与MySQL链接的客户端相当于事务管理器。要执行一个分布式事务,首先知道分布式事务涉及到哪些资源管理器,并且把每一个资源管理器中的事务执行到事务可以被提交叫或者回滚。通常使用两阶段提交法:(1)第一阶段,所有的分支被预备好。它们被Transaction-Manager告知要准备提交。每个分支Resource-Manger记录分支的行动并指示任务的可行性。而这些结果被用于第二阶段。(2)第二阶段,TM告知RMs是否要提交或者回滚。如果预备分支的时候各个分支都可行,那么就确认提交,如果有一个分支出错,那么就要全部回滚。特殊情况下,只有一个分支的时候,第二阶段则被省略。
       三、MySQL中分布式事务的漏洞分析
       考虑特殊情况:当一个事务分支处在PREPARE状态的时候失去了链接,在服务器重启以后虽然能看到为提交的事务,但是PREPARE之后的操作(包括提交或者回滚)没有写入binlog。这导致事务部分丢失或者主从数据库不一致。失败的例子如下:
      SessionA SessionB
      从student表中查找id为2的学生,结果集为空:
      mysql>select * from student where id=2; 从student表中查找id为2的学生,结果集为空:
      mysql>select * from student where id=2;
      启动事务test:mysql>xa start ‘test’,’TA’;
      加入一条记录并查看:mysql>insert into student values(2,’tomcat’,’003’);
      mysql>xa prepare ‘test’,’TA’;
      mysql>select * from student where id=2;
      name:id tomcat:2 查询刚才的记录,显示结果为空:
      mysql>select * from student where id=2;
      
      完成第一阶段,进入PREPARE状态。
      mysql>xa prepare ‘test’,’TA’;
      SessionA突然异常终止 查询分布式事务的状态:
      MySQL>xa recover\G
      formatID:1 gtrid_length:4 bqual_length:2
      SessionA被回滚 SessionA被回滚后,sessionB无法查看sessionA插入的记录,此时如果SessionB事务已被提交,则会导致分布式事务不完整。
      四、结束语
       MySQL虽然从5.0.3版本就开始支持了分布式事务,但是在特殊情况下是无法保证事务的完整性。主要原因就是在PREPARE状态的分支事务在遇到异常时没有记录到binlog,从而破坏了MySQL的日志恢复机制。MySQL也在不断完善中,将来或许通过日志机制改进来修复分布式事务中的漏洞。
      参考文献:
       [1]唐汉明.深入浅出MySQL[M].人民邮电出版社,2008
       [2]萨师煊,王珊.数据库系统概论[M].高等教育出版社,2000,2
       [3]郑振楣,于戈.分布式数据库[M].科学出版社,1999

    点赞 评论 复制链接分享
  • testcs_dn 微wx笑 2015-01-21 04:42
    点赞 评论 复制链接分享
  • rumlee rumlee 2015-01-22 00:33

    你说的这种需求,这是数据库最基本的了,还有什么解决方案可言啊。

    点赞 评论 复制链接分享

相关推荐