事务处理造成的数据库访问超时

 关于预算系统存在小部分模块超时的问题,我一直都认为是通过VPN访问服务器速度太慢所致。但是,我在.16测试服务器和我自己本地的部署的服务器进行测试的时候,超时情况仍然存在。查阅网上相关资料修改Web.config之类,延长所谓的数据库服务器会话时间,没有什么效果。

下面我以“科目明细导入”超时为例,讲解预算系统出现数据访问超时的主要原因。


 

之所以把问题给拿出来,是因为我想得出几个结论。首先,基于目前预算系统的架构,在一个的事务范围之内,对同一个表进行多次操作,如果存在某一个操作语句没有包括在事务当中,则会造成等待超时现象。(之所以这样,是因为事务对某一个表已经进行的锁定,事务之外的动作无法访问该表)

         其实,等待超时,也算是死锁的一种表现。回顾预算系统的多用户并发操作所造成的死锁现象,其实就是事务之间对表的交叉访问(这里的事务是不严谨的),造成线程之间的相互等待,都获取不了需要的资源,而造成的死锁现象。并发操作造成的死锁现象,这个问题的解决存在一定的复杂性,尚未有非常好的解决方法,只能从细节去抓。



这种事务机制,危害巨大。在引入数据库缓存依赖的时候,也同样因为这个问题报错







之所以报这种错误,是因为事务嵌套所致。在一个大的事务范围之类,子方法使用了引用了事务,但是在整个大的事务范围之内尚没有执行完成,而在方法中有把事务给Commit和Rollback了,所以事务已经执行完。而我们在另外一个方法中提交,将会导致事务的无法使用。

  /// <summary>
        /// 2013-01-18添加
        /// 封装DataBase的ExecuteDataSet函数,返回DataTable
        /// </summary>
        /// <param name="sqlCmd">字符型存储过程</param>
        /// <param name="pReadUncommitted">是否脏读</param>
        /// <param name="Params">参数列表</param>    
        /// <returns></returns>
        protected virtual DataTable ExecuteDataTable(string sqlCmd, bool pReadUncommitted, System.Data.Common.DbParameter[] Params,DbTransaction tran)
        {
            DataSet ds = null;
            DataTable dataTable = new DataTable();
            Database db = CreateDatabase();
            if (pReadUncommitted)
            {
                DbConnection conn = CreateDatabase().CreateConnection();
                conn.Open();

                try
                {

                    DbCommand dbcommand = db.GetSqlStringCommand(sqlCmd);
                    for (int i = 0; i < Params.Length; i++)
                    {
                        db.AddInParameter(dbcommand, Params[i].ParameterName, Params[i].DbType, Params[i].Value);
                    }
                    ds = db.ExecuteDataSet(dbcommand, tran);
                    //tran.Commit(); //在事务范围之内,不应该提交事务,所以注释了
                    if (ds.Tables.Count > 0)
                        dataTable = ds.Tables[0];
                    else
                        dataTable = null;
                    if (conn.State == ConnectionState.Open)
                        conn.Close();
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                    if (conn.State == ConnectionState.Open)
                        conn.Close();
                    throw ex;
                }

            }
            else
            {
                DbCommand dbcommand = db.GetSqlStringCommand(sqlCmd);
                for (int i = 0; i < Params.Length; i++)
                {
                    db.AddInParameter(dbcommand, Params[i].ParameterName, Params[i].DbType, Params[i].Value);
                }
                ds = db.ExecuteDataSet(dbcommand);
                if (ds.Tables.Count > 0)
                    dataTable = ds.Tables[0];
                else
                    dataTable = null;

            }
            return dataTable;
        }




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值