• 数据库事务原理与实现


    一.什么是数据库事务

    数据库事务是指作为单个逻辑工作单元执行的一系列操作.

    设想网上购物的一次交易,其付款过程至少包括以下几步数据库操作:
    · 更新客户所购商品的库存信息
    · 保存客户付款信息--可能包括与银行系统的交互
    · 生成订单并且保存到数据库中
    · 更新用户相关信息,例如购物数量等等
    正常的情况下,这些操作将顺利进行,最终交易成功,与交易相关的所有数据库信息也成功地更新。但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存信息时发生异常、该顾客银行帐户存款不足等,都将导致交易失败。一旦交易失败,数据库中所有信息都必须保持交易前的状态不变,比如最后一步更新用户信息时失败而导致交易失败,那么必须保证这笔失败的交易不影响数据库的状态--库存信息没有被更新、用户也没有付款,订单也没有生成。否则,数据库的信息将会一片混乱而不可预测。
    数据库事务正是用来保证这种情况下交易的平稳性和可预测性的技术。

    二.数据事务的ACID属性

    事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性:
    · 原子性(Atomicity)
    事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。通常,与某个事务关联的操作具有共同的目标,并且是相互依赖的。如果系统只执行这些操作的一个子集,则可能会破坏事务的总体目标。原子性消除了系统处理操作子集的可能性。
    · 一致性(Consistency)
    事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。某些维护一致性的责任由应用程序开发人员承担,他们必须确保应用程序已强制所有已知的完整性约束。例如,当开发用于转帐的应用程序时,应避免在转帐过程中任意移动小数点。
    · 隔离性(Isolation)
    由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。当事务可序列化时将获得最高的隔离级别。在此级别上,从一组可并行执行的事务获得的结果与通过连续运行每个事务所获得的结果相同。由于高度隔离会限制可并行执行的事务数,所以一些应用程序降低隔离级别以换取更大的吞吐量。
    · 持久性(Durability)
    事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

    三、事务保存点(SavePoint)

    有一个数据库管理员,在早上的时候,设置了一个保存点a1,然后工作(对数据库进行增删改查),到了中午他又设置了一个保存点a2,到了下午他又继续工作(还是对数据库进行增删改查),然后到了晚上。突然之间,他执行了一个很愚蠢的操作,把数据库里的数据全部给删除了!!!!

    那这个时候怎么办呢?好在他在早上和中午的时候设置了保存点,然后只要回到保存点就可以了。

    rollback to xxxSavePoint

    当事务commit之后,事务中设置的SavePoint就取消了

    四、事务并发

    两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:

    1、幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想。

    2、不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读。

    3、脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2所读取的行就无效,也就是脏数据。

    五、事务的隔离级别

    READ UNCOMMITTED 幻想读、不可重复读和脏读都允许。

    READ COMMITTED 允许幻想读、不可重复读,不允许脏读

    REPEATABLE READ 允许幻想读,不允许不可重复读和脏读

    SERIALIZABLE 幻想读、不可重复读和脏读都不允许

    Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以Oracle不支持脏读

    SQL标准所定义的默认事务隔离级别是SERIALIZABLE,但是Oracle 默认使用的是READ COMMITTED

    六、锁

          1)说明

    锁是一种机制,多个事务同时访问一个数据库对象时,该机制可以实现对并发的控制

    2) oracle中锁的类别

    1.DDL锁: oracle自动的施加和释放

    2.DML锁:事务开始时施加,使用Commit后者Rollback被释放、

    3.内部锁: 由oracle自己管理以保护内部数据库结构

    3)oracle锁的粒度

    1. 行级锁(TX):阻止该行上的DML操作,直到Commit或者Rollback

    2. 表级锁(TM):

    3. 数据库级锁: eg: 将数据库锁定为只读模式 alter database open read only;

    eg: 将数据库设置为限制模式(导入导出数据库时使用):alter system enable restricted session;

          4)锁的模式

      数字越大,级别越高

        5)死锁

    1. 说明

    1. 当两个用户希望持有对方的资源时就会发生死锁。即两个用户互相等待对方释放资源,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚。

    2. lORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件,详细描述死锁的相关信息。

    2.死锁产生条件

    1. Mutual exclusion(互斥):资源不能被共享,只能由一个进程使用。
    2. Hold and wait(请求并保持):已经得到资源的进程可以再次申请新的资源。
    3. No pre-emption(不可剥夺):已经分配的资源不能从相应的进程中被强制地剥夺。
    4. Circular wait(循环等待条件):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

    3. 事务和死锁预防总结

    1. 避免应用不运行长事务。

    2. 经常提交以避免长时间锁定行。

    3. 避免使用LOCK命令锁定表。

    4. 在非高峰期间执行DDL操作,在非高峰期间执行长时间运行的查询或事务。

  • 相关阅读:
    MySQL5.7的Linux安装shell脚本之二进制安装
    MySQL与Mongo简单的查询 1
    order by 与group by 之间排序问题
    说说左连接出现重复记录的问题
    MySQL5.6的Linux安装shell脚本之二进制安装(一)
    搭建简单FTP服务器以及过程中容易遇到的几个问题(一)
    jqurty
    jquery中的事件与动画
    SQL SERVER数据库设计与现实
    jquery2
  • 原文地址:https://www.cnblogs.com/zhulongchao/p/4758926.html
Copyright © 2020-2023  润新知