C# 事务处理

简单事务的一个常见例子:把钱从A账户转到B账户,这涉及两项任务,即从A账户把钱取出来;把钱存入B账户。两项任务要么同时成功,要么一起失败,给予回滚,以 便保持账户的状态和原来相同。否则,在执行某一个操作的时候可能会因为停电、网络中断等原因而出现故障,所以有可能更新了一个表中的行,但没有更新相关表 中的行。如果数据库支持事务,则可以将数据库操作组成一个事务,以防止因这些事件而使数据库出现不一致。

事务的ACID属性如下:

原子性(Atomicity):事务的所有操作是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。原子性消除了系统处理操作子集的可能性。

一致性(Consistency):数据从一种正确状态转换到另一种正确状态。事务在完成时,必须使所有的数据都保持一致。在相关数据库中,所有规则都必 须应用于事务的修改,以保持所有数据的完整性。当事务结束时,所有的内部数据结构都必须是正确的。在存款取款的例子中,逻辑规则是,钱是不能凭空产生或销 毁的,对于每个(收支)条目必须有一个相应的抵衡条目产生,以保证账户是平的。

隔离性(Isolation):由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。查看数据时数据所处的状态,要么是事务修改它之前的状态,要 么是事务修改它之后的状态。简单的理解就是,防止多个并发更新彼此干扰。事务在操作数据时与其他事务操作隔离。隔离性一般是通过加锁的机制来实现的。

持久性(Durability):事务完成之后,它对于系统的影响是永久性的。已提交的更改即使在发生故障时也依然存在。

对于事务的开发,.NET平台也为我们提供了几种非常简单方便的事务机制。无论是在功能上还是性能上都提供了优秀的企业级事务支持。

.NET开发者可以使用以下5种事务机制:

l         SQL和存储过程级别的事务。

l         ADO.NET级别的事务。

l         ASP.NET页面级别的事务。

l         企业级服务COM+事务。

l         System.Transactions 事务处理。

这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。

5.4.1  SQL和存储过程级别的事务

数据库 事务是其他事务模型的基础,当一个事务创建时不同数据库系统都有自己的规则。SQL Server默认在自动提交的模式下工作,每个语句执行完后都会立即提交;与此对照的是Oracle需要你包含一个提交语句。但是当一个语句通过OLE DB执行时,它执行完后一个提交动作会被附加上去。

例如:

DECLARE @TranName VARCHAR(20);

SELECT @TranName = ‘MyTransaction‘;

BEGIN TRANSACTION @TranName;

GO

USE AdventureWorks;

GO

DELETE FROM AdventureWorks.HumanResources.JobCandidate

    WHERE JobCandidateID = 13;

GO

COMMIT TRANSACTION MyTransaction;

GO

或者:

CREATE PROCEDURE Tran1 

as 

begin tran 

set xact_abort on

Insert Into P_Category(CategoryId,Name)values(‘1‘,‘test1‘) 

Insert Into P_Category(CategoryId,Name)values(‘2‘,‘test2‘) 

commit tran 

GO

set xact_abort on表示遇到错误立即回滚。

当然你也可以这么写:

CREATE PROCEDURE tran1

as

begin tran

Insert Into P_Category(CategoryId,Name)values(‘1‘,‘test1‘) 

if(@@error<>0)

 rollback tran

else

 begin

  Insert Into P_Category(CategoryId,Name)values(‘2‘,‘test2‘)

  if(@@error<>0)

   rollback tran

  else

   commit tran

 end

GO

数据库事务有它的优势和限制。

优势:

l         所有的事务逻辑包含在一个单独的调用中。

l         拥有运行一个事务的最佳性能。

l         独立于应用程序。

限制:

l         事务上下文仅存在于数据库调用中。

l         数据库代码与数据库系统有关。

5.4.2  ADO.NET级别的事务

现在我们对事务的概念和原理都有所了解了,并且作为已经有一些基础的C#开发者,我们已经熟知编写数据库交互程序的一些要点,即:

(1)使用SqlConnection类的对象的Open()方法建立与数据库服务器的连接。

(2)然后将该连接赋给SqlCommand对象的Connection属性。

(3)将欲执行的SQL语句赋给SqlCommand的CommandText属性。

(4)通过SqlCommand对象进行数据库操作。

创建一 个ADO.NET事务是很简单的,需要定义一个SqlTransaction类型的对象。SqlConnection 和OleDbConnection对象都有一个 BeginTransaction 方法,它可以返回 SqlTransaction 或者OleDbTransaction 对象。然后赋给SqlCommand对象的Transcation属性,即实现了二者的关联。为了使事务处理可以成功完成,必须调用 SqlTransaction对象的Commit()方法。如果有错误,则必须调用Rollback()方法撤销所有的操作。

基于以上认识,下面我们就开始动手写一个基于ADO.NET的事务处理程序。

string conString = "data source=127.0.0.1;database=codematic;user id=sa;

password=";

SqlConnection myConnection = new SqlConnection(conString);

myConnection.Open();

//启动一个事务

SqlTransaction myTrans = myConnection.BeginTransaction();

//为事务创建一个命令

SqlCommand myCommand = new SqlCommand();

myCommand.Connection = myConnection;

myCommand.Transaction = myTrans;

try

{

    myCommand.CommandText = "update P_Product set Name=‘电脑2‘ where Id=52";

    myCommand.ExecuteNonQuery();

    myCommand.CommandText = "update P_Product set Name=‘电脑3‘ where Id=53";

    myCommand.ExecuteNonQuery();

    myTrans.Commit();//提交

    Response.Write("两条数据更新成功");

}

catch (Exception ex)

{

    myTrans.Rollback();//遇到错误,回滚

    Response.Write(ex.ToString());              

}

finally

{

    myConnection.Close();

}

ADO.NET事务的优势和限制如下。

优势:

l         简单。

l         和数据库事务差不多快。

l         事务可以跨越多个数据库访问。

l         独立于数据库,不同数据库的专有代码被隐藏了。

限制:事务执行在数据库连接层上,所以需要在执行事务的过程中手动地维护一个连接。

注意:所有命令都必须关联在同一个连接实例上,ADO.NET事务处理不支持跨多个连接的事务处理。

ASP.NET 事务可以说是在.NET平台上事务实现方式最简单的一种,你仅仅需要一行代码即可。在aspx的页面声明中加一个额外的属性,即事务属性 Transaction="Required",它有如下的值:Disabled(默认)、NotSupported、Supported、 Required和RequiresNew,这些设置和COM+及企业级服务中的设置一样,典型的一个例子是如果你想在页面上下文中运行事务,那么要将其 设置为Required。如果页面中包含有用户控件,那么这些控件也会包含到事务中,事务会存在于页面的每个地方。5.4.3  ASP.NET页面级别的事务

页面声明Transaction="Required":

<%@ Page Transaction="Required"  Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication4.WebForm3" %>

页面引用:using System.EnterpriseServices;。

然后,数据操作代码:

protected void Button1_Click(object sender, EventArgs e)

{

    try

    {

        Work1();

        Work2();

        ContextUtil.SetComplete();     //提交事务

    }

    catch (System.Exception except)

    {

        ContextUtil.SetAbort();        //撤销事务

        Response.Write(except.Message);

    } 

} 

private void Work1()

{

    string conString = "data source=127.0.0.1;database=codematic;user id=sa;

        password=";

    SqlConnection myConnection = new SqlConnection(conString);

    string strSql = "Insert Into P_Category(CategoryId,Name)values(‘1‘,

        ‘test1‘)";

    SqlCommand myCommand = new SqlCommand(strSql, myConnection);

    myConnection.Open();

    int rows = myCommand.ExecuteNonQuery();

    myConnection.Close();

}

private void Work2()

{

    string conString = "data source=127.0.0.1;database=codematic;user id=sa;

        password=";

    SqlConnection myConnection = new SqlConnection(conString);

    string strSql = "Insert Into P_Category(CategoryId,Name)values(‘2‘,

        ‘test2‘)";

    SqlCommand myCommand = new SqlCommand(strSql, myConnection);

    myConnection.Open();

    int rows = myCommand.ExecuteNonQuery();

    myConnection.Close();

}

ContextUtil是用于获取 COM+ 上下文信息的首选类。由于此类的成员全部为static,因此在使用其成员之前不需要对此类进行实例化。

ASP.NET页面事务的优势和限制如下。

l         优势:实现简单,不需要额外的编码。

l         限制:页面的所有代码都是同一个事务,这样的事务可能会很大,而也许我们需要的是分开的、小的事务实现在Web层。

5.4.4  企业级服务COM+事务

.NET Framework 依靠 MTS/COM+ 服务来支持自动事务处理。COM+ 使用 Microsoft Distributed Transaction Coordinator(DTC)作为事务管理器和事务协调器在分布式环境中运行事务。这样可使 .NET 应用程序运行跨多个资源结合不同操作(例如将定单插入SQL Server 数据库、将消息写入 Microsoft 消息队列(MSMQ)队列,以及从 Oracle 数据库检索数据)的事务。

要 实现COM+事务处理的类则必须继承System.EnterpriseServices.ServicedComponent,这些类需要是公共的,并 且需要提供一个公共的默认的构造器。其实Web Service就是继承ServicedComponent,所以Web Service也支持COM+事务。要在类定义之前加属性[Transaction(TransactionOption.Required)]。类里面 的每个方法都会运行在一个事务中。

定义一个COM+事务处理的类:

首先引用:using System.EnterpriseServices;

然后继承:ServicedComponent。

[Transaction(TransactionOption.Required)]

public class OrderData : ServicedComponent

{

}

TransactionOption枚举类型支持5个值:Disabled、NotSupported、Required、RequiresNew和Supported,如表5-3所示。

表5-3  TransactionOption枚举类型支持5个值



说    明


Disabled


忽略当前上下文中的任何事务


NotSupported


使用非受控事务在上下文中创建组件


Required


如果事务存在则共享事务,并且如有必要则创建新事务


RequiresNew


使用新事务创建组件,而与当前上下文的状态无关


Supported


如果事务存在,则共享该事务

一般来说COM+中的组件需要Required 或Supported。当组件用于记录或查账时RequiresNew 很有用,因为组件应该与活动中其他事务处理的提交或回滚隔离开来。

派生类可以重载基类的任意属性。如OrderData选用Required,派生类仍然可以重载并指定RequiresNew或其他值。

COM+ 事务有手动处理和自动处理两种方式,自动处理就是在所需要自动处理的方法前加上[AutoComplete],根据方法的正常或抛出异常决定提交或回滚。 手动处理就是调用ContextUtil类中的EnableCommit、SetComplete和SetAbort方法。

实现步骤如下。

1.给程序添加强名

1)创建一对密钥

用来创建密钥的工具是称为sn.exe的共享工具。通常通过命令提示运行它,该工具可执行各种任务以生成并提取密钥。我们需要用以下方式来运行sn.exe。

sn –k c:\key.snk

其中key.snk 代表将保存密钥的文件的名称。它的名称可以是任意的,不过习惯上带有.snk后缀名。

2)签名

这个文件必须在AssemblyKeyFile属性中引用,签名通常是在编译时进行的。签名时,用户可利用C#属性通知编译器应该使用正确的密钥文件对DLL进行签名。要做到这一点用户需要打开工程中的AssemblyInfo.cs文件并进行修改。

[assembly:AssemblyKeyFile(“..\\..\\key.snk”)]

注  意:key.snk文件和项目文件在同一个文件夹内。

创建一个项目用以实现事务处理的业务类ClassTran。2.手动事务处理

using System;

using System.Data.SqlClient;

using System.EnterpriseServices; //企业级服务COM+事务

namespace ClassTran

{

    [Transaction(TransactionOption.Required)]

    public class OrderData1 : ServicedComponent

    {

        //手动事务

        public string WorkTran()

        {

            try

            {

                ContextUtil.EnableCommit();

                Work1();

                Work2();

                ContextUtil.SetComplete();

                return "成功!";

            }

            catch (Exception ex)

            {

                ContextUtil.SetAbort();

                return "失败!";

            }

        }

        private void Work1()

        {

            string conString = "data source=127.0.0.1;database=codematic;

                 user id=sa;password=";

            SqlConnection myConnection = new SqlConnection(conString);

            string strSql = "Insert Into P_Category(CategoryId,Name)

                 values(‘1‘,‘test1‘)";

            SqlCommand myCommand = new SqlCommand(strSql, myConnection);

            myConnection.Open();

            int rows = myCommand.ExecuteNonQuery();

            myConnection.Close();

        }

        private void Work2()

        {

            string conString = "data source=127.0.0.1;database=codematic;

                 user id=sa;password=";

            SqlConnection myConnection = new SqlConnection(conString);

            string strSql = "Insert Into P_Category(CategoryId,Name)

                 values(‘2‘,‘test2‘)";

            SqlCommand myCommand = new SqlCommand(strSql, myConnection);

            myConnection.Open();

            int rows = myCommand.ExecuteNonQuery();

            myConnection.Close();

        }

    }

}

3.自动事务处理

在方法之前增加属性[AutoComplete(true)],这样如果方法执行时没有异常就默认提交,如果有异常则这个方法就会回滚。

using System;

using System.Data.SqlClient;

using System.EnterpriseServices;//企业级服务COM+事务

namespace ClassTran

{

    [Transaction(TransactionOption.Required)]

    public class OrderData2 : ServicedComponent

    {

        //自动事务

        [AutoComplete(true)]

        public string WorkTran()

        {

            string msg = "";

            string conString = "data source=127.0.0.1;database=codematic;

                 user id=sa;password=";

            SqlConnection myConnection = new SqlConnection(conString);

            myConnection.Open();                                   

            SqlCommand myCommand = new SqlCommand();

            myCommand.Connection = myConnection;           

            try

            {

                myCommand.CommandText = "update P_Product set Name=‘电脑2‘

                  where Id=52";

                myCommand.ExecuteNonQuery();

                myCommand.CommandText = "update P_Product set Name=‘电脑3‘

                  where Id=53";

                myCommand.ExecuteNonQuery();

                msg ="成功!";

            }

            catch (Exception ex)

            {

                msg = "失败:"+ex.Message;              

            }

            finally

            {

                myConnection.Close();

            }

            return msg;

        }

    }

}

4.事务方法调用

protected void Button1_Click(object sender, EventArgs e)
{

    ClassTran.OrderData1 od1 = new ClassTran.OrderData1();

    od1.WorkTran();

}

protected void Button2_Click(object sender, EventArgs e)
{

    ClassTran.OrderData2 od2 = new ClassTran.OrderData2();

    od2.WorkTran();

}

在需要事务跨 MSMQ 和其他可识别事务的资源(例如SQL Server 数据库)运行的系统中,只能使用 DTC 或 COM+ 事务,除此之外没有其他选择。DTC 协调参与分布式事务的所有资源管理器,也管理与事务相关的操作。

企业级服务COM+事务的前提及优缺点如下。

前提:

l         需要强名字。

l         使用事务的对象需要继承ServicedComponent。

优势:

l         执行分布式事务,多个对象可以轻松地运行在同一个事务处理中,事务处理还可以自动登记。

l         获得COM+服务,诸如对象构建和对象池等。

缺点:

l         由于存在 DTC 和 COM 互操作性开销,导致性能降低。

l         COM+ 1.0要求每个事务的隔离级别都设置为Serializable。

l         使用Enterprise Services的事务总是线程安全的, 也就是说你无法让多个线程参与到同一个事务中。

5.4.5  System.Transactions 事务处理

在 .NET Framework 2.0中增加了System.Transactions,这是一种新的命名空间,完全专注于控制事务性行为。引入了执行事务性工作的更简单方法及一些新的 性能优化。System.Transactions提供了一个“轻量级”的、易于使用的Transaction框架。

在上节 中,要实现Transaction需要利用EnterpriseServices,让组件从ServiceComponent继承下来。而通过 System.Transactions,则只要简单的几行代码,不需要继承,不需要Attribute标记。用户根本不需要考虑是简单事务还是分布式事 务。新模型会自动根据事务中涉及的对象资源判断使用何种事务管理器。简而言之,对于任何的事务,用户只要使用同一种方法进行处理即可。

下面介绍System.Transactions的几种用法。

首先要引用:using System.Transactions;。

其次,将事务操作代码放在TransactionScope中执行。如:

using (TransactionScope ts = new TransactionScope())

{

//事务操作代码

ts.Complete();

}

这 是最简单,也是最常见的用法。创建了新的 TransactionScope 对象后,即开始创建事务范围。如代码示例所示,建议使用 using 语句创建范围。位于 using 块内的所有操作将成为一个事务的一部分,因为它们共享其所定义的事务执行上下文。本例中的最后一行,调用 TransactionScope 的 Complete 方法,将导致退出该块时请求提交该事务。此方法还提供了内置的错误处理,出现异常时会终止事务。

using (TransactionScope ts = new TransactionScope())//使整个代码块成为事务性代码

{

    #region 在这里编写需要具备Transaction的代码

    string msg = "";

    string conString = "data source=127.0.0.1;database=codematic;user id=sa;password=";

    SqlConnection myConnection = new SqlConnection(conString);

    myConnection.Open();

    SqlCommand myCommand = new SqlCommand();

    myCommand.Connection = myConnection;

    try

    {

        myCommand.CommandText = "update P_Product set Name=‘电脑2‘ where Id=52";

        myCommand.ExecuteNonQuery();

        myCommand.CommandText = "update P_Product set Name=‘电脑3‘ where Id=53";

        myCommand.ExecuteNonQuery();

        msg = "成功!";

    }

    catch (Exception ex)

    {

        msg = "失败:" + ex.Message;

    }

    finally

    {

        myConnection.Close();

    }

    #endregion

    ts.Complete();

    return msg;              

}           

上面的代码演 示了在一个Transaction Scope里面打开一个数据库连接的过程。这个数据库连接由于处在一个Transaction Scope里面,所以会自动获得Transaction的能力。如果这里数据库连接的是SQL Server 2005,那么这个Transaction将不会激活一个MSDTC管理的分布式事务,而是会由.NET创建一个Local Transaction,性能非常高。但是如果是SQL Server 2000,则会自动激活一个分布式事务,在性能上会受一定的损失。

再看下面的例子:

void MethodMoreConn()

{

    using (TransactionScope ts = new TransactionScope())

    {

        using (SqlConnection conn = new SqlConnection(conString1))

        {

            conn.Open();

            using (SqlConnection conn2 = new SqlConnection(conString2))

            {

                conn2.Open();

            }

        }

        ts.Complete();

    }

}

这个例子更加 充分地说明了Transaction Scope的强大,两个数据库连接!虽然上面的conn和conn2是两个不同的连接对象,可能分别连接到不同的数据库,但是由于它们处在一个 TransactionScope中,它们就具备了“联动”的Transaction能力。在这里,将自动激活一个MSDTC管理的分布式事务(可以通过 打开【管理工具】里面的组件服务,来查看当前的分布式事务列表)。

1.在分布式事务中登记

ADO.NET 2.0 中的新增功能支持使用 EnlistTransaction 方法在分布式事务中登记。由于 EnlistTransaction 在 Transaction 实例中登记连接,因此,该方法利用 System.Transactions 命名空间中的可用功能来管理分布式事务,从而比使用 System.EnterpriseServices. ITransaction 对象的 EnlistDistributedTransaction 更可取。此外,其语义也稍有不同:在一个事务中显式登记了某个连接后,如果第一个事务尚未完成,则无法取消登记或在另一个事务中登记该连接。

void MethodEnlist()

{

    CommittableTransaction tx = new CommittableTransaction();

    using (SqlConnection conn = new SqlConnection(conString))

    {

        conn.EnlistTransaction(tx);

    }

    tx.Commit();

}

2.实现嵌套事务范围

void RootMethod()

{

    using (TransactionScope scope = new TransactionScope())

    {

        //操作代码

        SonMethod();//子事务方法

        scope.Complete();

    }

}

void SonMethod()

{

    using (TransactionScope scope = new TransactionScope())

    {

        //操作代码

        scope.Complete();

    }

}

3.事务范围附加选项

如果你 想要保留代码部分执行的操作,并且在操作失败的情况下不希望中止环境事务,则Suppress对你很有帮助。例如,在你想要执行日志记录或审核操作时,不 管你的环境事务是提交还是中止,上述值都很有用。该值允许你在事务范围内具有非事务性的代码部分,如以下示例所示。

void MethodSuppress()

{

    using (TransactionScope scope1 = new TransactionScope())//开始事务

    {

        try

        {

            //开始一个非事务范围

            using (TransactionScope scope2 = new TransactionScope(

                 TransactionScopeOption.Suppress))

            {

                //不受事务控制代码

            }

            //从这里开始又回归事务处理

        }

        catch

        { }       

    }

}

虽然.NET 2.0对事务提供了很好的支持,但是没有必要总是使用事务。使用事务的第一条规则是,在能够使用事务的时候都应该使用事务,但是不要使用过度。原因在于, 每次使用事务都会占用一定的开销。另外,事务可能会锁定一些表的行。还有一条规则是,只有当操作需要的时候才使用事务。例如,如果只是从数据库中查询一些 记录,或者执行单个查询,则在大部分时候都不需要使用显式事务。

开发人员应该在头脑中始终保持一个概念,就是用于修改多个不同表数据的冗长事务会严重妨碍系统中的所有其他用户。这很可能导致一些性能问题。当实现一个事务时,遵循下面的实践经验能够达到可接受的结果:

l         避免使用在事务中的Select返回数据,除非语句依赖于返回数据。

l         如果使用Select语句,则只选择需要的行,这样不会锁定过多的资源,而尽可能地提高性能。

l         尽量将事务全部写在T-SQL或者API中。

l         避免事务与多重独立的批处理工作结合,应该将这些批处理放置在单独的事务中。

l         尽可能避免大量更新。

另外,必须注意的一点就是事务的默认行为。在默认情况下,如果没有显式地提交事务,则事务会回滚。虽然默认行为允许事务的回滚,但是显式回滚方法总是一个良好的编程习惯。这不仅仅只是释放锁定数据,也将使得代码更容易读取并且更少错误。

.NET提供的事务功能很强大,具体的内容远不止本文所讲解的这样简单。本文只是起到一个抛砖引玉的功能。希望读者能够灵活恰当地使用事务功能,而不要过度使用事务,否则可能会对性能起到消极的作用。

原文地址:http://www.cnblogs.com/bicabo/archive/2011/11/14/2248044.html

时间: 2024-11-05 15:56:34

C# 事务处理的相关文章

数据库的事务处理---PDO实现

事务处理用一句简单的术语称为"原子操作",即一件事情,要么全部完成,要么一个也别完成:有一种一荣俱荣,一损俱损的感觉. 最常用的就是在交易过程中,比如在网络中,甲方付费给乙方,钱确认付款,但是乙方并未确认收款,那么,甲方的账户并不会减少,乙方的账户也并不会增加. 只有当甲方确认付款,乙方确认收款,两个步骤都完成,并且不出现错误的时候,双方的账户才会改变 看代码也许更好理解 1 <?php 2 try{ 3 $pdo=new PDO("mysql:host=localho

mysql 事务处理

知识点: 事务处理是什么? 当数据库表呈树状机构设计时,我们对一个表进行增.删.改的操作,可能会要求对另外的表进行相同的操作,为了保证这多个sql能同时执行成功,就要使用mysql的事务处理. 注意:只有增删改的操作可以进行回滚,alter等操作不可行! 事务特性: 1.原子性:所有的sql执行操作必须全部成功,否则则回滚到处理前状态 2.一致性: 确保数据库正确地改变状态后,成功提交的事务. 3.隔离性: 使事务操作彼此独立的和透明的. 4.持久性: 确保提交的事务的结果或效果的系统出现故障的

第一次接触终极事务处理——Hekaton

在这篇文章里,我想给出如何与终极事务处理(Extreme Transaction Processing (XTP) )的第一步接触,即大家熟知的Hakaton.如果你想对XTP有个很好的概况认识,我推荐Kalen Delaney写的关于它的白皮书,另外微软研究院也发布了题为“对于内存数据库的高性能并发控制机制(High-Performance Concurrency Control Mechanisms for Main-Memory Databases)”的研究白皮书,点此下载. 所有XTP维

JDBC的进化3--补充:事务处理

接着JDBC的进化3,我们来说数据库事务. 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态. 怎么理解呢? 一组逻辑单元:我认为指的是多条的DML操作,只是一条DML语句的话,对于mysql来说,执行完成功就自动提交了,没成功的话,就没成功喽,这样说来,一条DML语句就相当于一个原子,不可再分了. 从一种状态变换到另一种状态:即这组操作是成功了还是失败了,他们必须同时都成功,有一个失败,就退回到起点.例如银行的转账,不能一个成功,一个失败吧. 来看看JDBC的事务处理: 先来看看,在什

Redis缓存技术学习系列之事务处理

?在本系列的第一篇文章中,我们主要针对Redis中的"键"和"值"进行了学习.我们可以注意到,Redis是一个C/S架构的数据库,在我们目前的认知中,它是通过终端中的一条条命令来存储和读取的,即它是一个非常典型的"请求-响应"模型.可是我们知道在实际的应用中,我们要面对的或许是更为复杂的业务逻辑,因为Redis中不存在传统关系型数据库中表的概念,因此在使用Redis的过程中,我们要面对两个实际的问题,即如何更好的维护数据库中的"键&qu

分布式系统的事务处理【转】

转:http://coolshell.cn/articles/10910.html 当我们在生产线上用一台服务器来提供数据服务的时候,我会遇到如下的两个问题: 1)一台服务器的性能不足以提供足够的能力服务于所有的网络请求. 2)我们总是害怕我们的这台服务器停机,造成服务不可用或是数据丢失. 于是我们不得不对我们的服务器进行扩展,加入更多的机器来分担性能上的问题,以及来解决单点故障问题. 通常,我们会通过两种手段来扩展我们的数据服务: 1)数据分区:就是把数据分块放在不同的服务器上(如:uid %

PHP MYSQLI中事务处理

MYSQL事务处理让所有sql语句执行成功后才去处理,如果有一条没有成功或者报错就会回滚事务,防止敏感操作处理失败.MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其它类型是不支持的! $mysqli->autocommit(FALSE); //关闭自动提交功能 $sql = "UPDATE users SET money = money-300 WHERE username = 'Mike'"; $res1 = $mysqli->query($sql);

数据库事务处理机制之事务回滚问题讨论

一.Sql中的事务 概念:事物是一种机制,是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行.事务是一个不可分割的工作逻辑单元.在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的.多用户登录系统适于使用事务机制. 属性:4大属性: a.原子性:事务时一个完整的操作.b.一致性:当事务完成时,数据库必须处于一致状态.c.隔离性:对数据进行修改的所有并发事务时彼此隔离的.d.持久性:事务完成后,它对于系统的影响是永久性的. 创建 (1)开始事务:begin t

JDBC编程之事务处理

JDBC中的事务处理指的是事务的一致性等问题,例如插入一条数据(id,name,password)到表中,另一条数据(address,id)到另一张表中,并且两条数据是相关联的,那么假设第一条数据插入成功,但是第二条数据由于异常没有插入成功,那么此时为了保证事务的一致性.完整性,则两条数据都不能够插入. 1. 创建Conn连接类 Conn.java 1 package com.test.conn; 2 3 import java.sql.Connection; 4 import java.sql

oracle学习篇六:更新操作、事务处理

----------------1.数据库更新操作----------------------------- select * from tab;--查询表 drop table siebel_user;--删除表 --copy一份表结构create table myemp as select * from emp; select * from myemp; --插入记录insert into myemp(empno,ename,job,hiredate,sal,comm,deptno) val