分布式数据库系统---商旅预定系统的实现(11)

事务处理过程

        事务的处理过程大体分为几个步骤:1.事务的组装;2.相应数据集合的加锁;3.通知数据集合备份;4.顺序执行每一个原子操作;5.为每一个原子操作的成功位做标示;6存储结果返回到结果池中

        事务的组装在客户端需要自行完成,因为每个客户端提交的任务不相同,服务器都做统一的处理。事务组装的代码如下:

            Boolean success = false;
            #region 组装成一个事务,并返回结果
            TransactionEntity transactionEntity = new TransactionEntity();//准备提交的参数
            Hashtable ResultHashTable = new Hashtable();//准备返回的参数
            transactionEntity.TransactionID.Add("14");//编号21:预订酒店
            transactionEntity.TransactionParam.Add(new object[] { locationString, hotelRemoteService });//参数
            transactionEntity.TransactionID.Add("19");//编号19:添加预订信息
            transactionEntity.TransactionParam.Add(new object[] { CustNameString, 2, reservationRemoteService });//参数
            queueTransactionService.intTransactionID += 1;//事务编号
            int intTransactionID = queueTransactionService.intTransactionID;
            queueTransactionService.globalControlService = globalControlService;//分配新的事务编号
            queueTransactionService.AddEntity(intTransactionID.ToString(), transactionEntity);//把需要处理的事务装在hashtable队列里面,等待程序自动处理
            while (true)//循环检查结果队列,查找自己的事务结果
            {
                if (queueTransactionService.TransactionResult.ContainsKey(intTransactionID.ToString()))//在结果列表中查找到了自己需要的数据,跳出无限等待
                    break;
            }
            ResultHashTable = (Hashtable)queueTransactionService.TransactionResult[intTransactionID.ToString()];//接受从服务器来的结果
            success = (Boolean)ResultHashTable["14"];
            if (success == true)
            {
                MessageBox.Show("酒店预定成功,地点:" + locationString);
            }
            else
            {
                MessageBox.Show("酒店预定失败!");
            }
            #endregion


 

        事务的组装首先需要实例化事务实体类(TransactionEntiy)和结果接受类(Hashtable)。下一步需要填充TransactionEntiy,整个TransactionEntiy只有三个参数,两个需在这里填充,只有每个操作是否成功需要在客户端填充并且处理检测。添加好事务的序号后,客户端需要做的就是把事务丢进事务池(Transaction Pool)中等待程序区运行。这时候客户端需要族的就是去结果池(Result Pool)中等待并且寻找自己的结果。示例图如下:

事务池和结果池

 

        在执行这个事务之前,需要对其所涉及的所有数据集合进行加锁,即修改其hasControl标志段的值。在对其加锁的同时,也通知该数据集合进行备份,以便事务撤销的时候不能恢复到原来的状态。代码片段如下:

        /// <summary>
        /// 执行一个事务,把结果存储在Hashtable中,此过程会自动加锁,对数据集合进行备份
        /// </summary>
        /// <param name="TansactionHashTable">需要执行的事务,包括每一个操作的编号和所需要的参数</param>
        /// <returns>返回结果,按照每一个操作得到的结果存储在Hashtable里面</returns>
        public Hashtable ProcessTransaction()
        {
            for (int i = 0; i < TransactionEntity.TransactionID.Count; i++)
            {
                //对所需要的数据集合进行加锁
                LockByID(TransactionEntity.TransactionID[i]);
                //开始这个事务,通知相关数据集合服务器做相应的处理
                BeginByID(TransactionEntity.TransactionID[i], xid);
            }

 

      循环遍历事务中的每一个操作,找到其编号,根据编号执行相应的操作,并把结果放在相应的集合中。

            Hashtable TransactionResult = new Hashtable();
            for (int i = 0; i < TransactionEntity.TransactionID.Count; i++)
            {
                try
                {
                    //把方法编号和方法返回结果存储到hashtable里面,用于返回给客户端
                    object ObjResultTmp = GetDataByID(TransactionEntity.TransactionID[i], TransactionEntity.TransactionParam[i]);
                    if (ObjResultTmp == null)//如果该返回值为空,则说明没有取到数据或者操作失败,则执行失败
                        TransactionEntity.Success.Add(false);
                    else
                        TransactionEntity.Success.Add(true);
                    TransactionResult.Add(TransactionEntity.TransactionID[i], ObjResultTmp);
                }
                catch (Exception e)
                {
                    TransactionEntity.Success.Add(false);
                }
            }


 

        一次事务的执行并不一定能成功,如果有一个操作失败了,那么就意味着整个事务都必须要回滚到初始状态,所以在每一个操作执行完毕后,都会为其标志位进行赋值。标志为失败的情况主要分为几个情况:1.返回结果为空,说明执行失败;2.执行存在错误跑到Catch区域了。这两种情况都视为操作失败。

            int flag = 1;//标记为,1为全部成功,0为有失败
            //通过循环来查看是否有那个执行没有成功
            for (int i = 0; i < TransactionEntity.Success.Count; i++)
            {
                if (TransactionEntity.Success[i].Equals(false))//如果有失败的操作,那么将整个事务回滚,具体操作为还原相应的数据集合
                {
                    flag = 0;//有失败
                    break;
                }
            }


 

无论此事务成功或者失败,都需要给数据集合一个交代。事务执行的最后,需要做的就是判断此事务是需要提交还是回滚。

            //判断是否进行回滚
            if (flag == 0)//到此,失败,回滚
                for (int i = 0; i < TransactionEntity.TransactionID.Count; i++)
                {
                    RollBackByID(TransactionEntity.TransactionID[i], xid);
                }
            else
                for (int i = 0; i < TransactionEntity.TransactionID.Count; i++)
                {
                    //到此,说明整个事务执行成功
                    CommiteByID(TransactionEntity.TransactionID[i], xid);
                }

            //执行结束,解锁
            for (int i = 0; i < TransactionEntity.TransactionID.Count; i++)
            {
                UnlockByID(TransactionEntity.TransactionID[i]);
            }


 

最后无论回滚还是执行,都需要释放掉所占用的资源,保证其他事务能够正常运行。

 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值