zoukankan      html  css  js  c++  java
  • 事务(Transaction)

    之前在学校学的数据库系统概论基本上快忘光了,都是停留在概念上,直到这几天在学习Dapper的时候才看到用到了数据库事务来批处理多条sql语句。

    首先回顾一下课本上的关于数据库事务的概念:

    事务提供了一种机制,可用来将一系列数据库更改归入一个逻辑操作。更改数据库后,所做的更改可以作为一个单元进行提交或取消。事务可确保遵循原子性、一致性、隔离性和持续性(ACID)这几种属性,以使数据能够正确地提交到数据库中。
    使用事务机制的好处非常明显,例如银行转账之类的交易操作中,事务有着重要的作用。事务的成功取决于事务单元帐户相互依赖的操作行为是否能全部执行成功,只要有一个操作行为失败,整个事务将失败。例如:客户A和客户B的银行账户金额都是10000元人民币,客户A需要把自己帐户中的5000元人民币转到客户B的账户上。这个过程看似简单,实际上涉及了一系列的数据库操作,可以简单地视为两步基本操作,即从客户A帐户的金额中扣除5000元人民币,以及将客户B帐户中金额添加5000元人民币。假设第1步数据库操作成功,而第二步失败的话,将导致整个操作失败,并且客户A帐户金额将被扣除5000元人民币。事务机制可以避免此类情况,以保证整个操作的完成,如果某步操作出错,之前所作的数据库操作将全部失效。
    【分析】
    事务是单个的工作单元。如果某个事务成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分。如果事务遇到错误且必须取消或回滚,则所有数据更改均被清除。一个逻辑工作单元必须有ACID属性,只有这样才能成为一个事务。ACID属性有以下4个属性。
    1.原子性
    事务必须是原子工作单元。对于其数据修改,要么全都执行,要么全都不执行。
    2.一致性
    事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构都必须是正确的。
    3.隔离性
    由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务识别数据时数据所处的状态,或者是另一个并发事务修改它之前的状态,或者是第二个事务修改它之后的状态,事务不会识别中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
    4.持久性
    事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
    事务有以下3种运行模式。
    q      自动提交事务:每条单独的语句都是一个事务。
    q      显式事务:每个事务均以BEGIN TRANSACTION语句显式开始,以COMMIT或ROLLBACK语句显式结束。
    q      隐性事务:在上个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句显式完成。

    我在本地创建了一个Student的数据库里面有一张名为studentinfo的表,由事务在Dapper中向数据库插入两条数据(如果对Dapper不熟悉的话可以参考后续的随笔,其实就是一种以sql语句为主导轻型的ORM)

     1  private static void Main(string[] args)
     2         {
     3             IDbConnection connection = new SqlConnection(@"Data Source=.;Initial Catalog=Student;Integrated Security=True");
     4 
     5             connection.Open();
     6             // Start transaction
     7             IDbTransaction transaction = connection.BeginTransaction();
     8             try
     9             {
    10                 string queryA = "insert into studentinfo values(@name,@age,@address)";
    11                 string queryB = "insert into studentinfo values(@name,@age,@address)";
    12                 connection.Execute(queryA, new { name = "WangHaoqiang", age = 15, address = "Anhui" }, transaction);
    13                 connection.Execute(queryB, new { name = "Wangqiang", age = 20, address = "Henan" }, transaction);
    14                 // Commit
    15                 transaction.Commit();
    16             }
    17             catch (Exception ex)
    18             {
    19                 transaction.Rollback();
    20                 throw new Exception(ex.Message);
    21             }
    22             Console.WriteLine("execute successfully!");
    23             connection.Close();
    24             Console.ReadKey();
    25         }

    可以看到插入到本地数据库的两条数据:

  • 相关阅读:
    STL逆序迭代器(reverse_iterator)
    STL容器之vector容器API(二)
    STL容器之vector容器巧用swap收缩空间
    STL容器之vector容器API(一)
    STL容器vector概念和注意事项(每次扩充都会重新开辟空间,释放原空间,即首元素地址会变一次)
    STL容器之string内存重定义
    STL容器之string与c_style类型转换
    STL容器之string插入和删除
    STL容器之string字串
    STL容器之string比较
  • 原文地址:https://www.cnblogs.com/AngryShoes/p/7758040.html
Copyright © 2011-2022 走看看