static,你还敢用吗?(二)

作者: buguge | 来源:发表于2017-01-05 19:01 被阅读545次

为了压系统,昨天小组在测试环境模拟了一大批订单数据。今天上午查看记录的账单计息日志,发现了一大堆的MySqlException

MySql.Data.MySqlClient.MySqlException (0x80004005): 
There is already an open DataReader associated with this Connection which must be closed first.

诸如:

2017-01-05 00:40:49.891
账单计息异常/{"BillId":1000012082,"OrderId":"DD201701040002672"}:MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first.
   在 MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
   在 MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex)
   在 MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   在 MySql.Data.MySqlClient.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   在 System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
   在 CommonLibrary.CommonOrm.CommonOrm_Dapper.<QueryImpl>d__11`1.MoveNext() 位置 e:\work\yijia\trunk\CommonLibrary\CommonOrm\CommonOrm_Dapper.cs:行号 1554
   在 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   在 CommonLibrary.CommonOrm.CommonOrm_Dapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) 位置 e:\work\yijia\trunk\CommonLibrary\CommonOrm\CommonOrm_Dapper.cs:行号 1444
   在 GateWay.DAL.BillsDal.BillsDal.GetOrdersBillList(String bizOrderId) 位置 e:\work\yijia\trunk\GetWay.DAL\BillsDal\BillsDal.cs:行号 123
   在 GateWay.BLL.Bills.BillsBll.GetOrdersBill(String bizOrderId, BillTypeEnum billType) 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\BillsBll.cs:行号 27
   在 GateWay.BLL.Bills.PrincipalBillsInterest.InterestBill(t_bills principleBill) 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\PrincipalBillsInterest.cs:行号 186
   在 GateWay.BLL.Bills.PrincipalBillsInterest.Interest() 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\PrincipalBillsInterest.cs:行号 77

通过分析程序,发现dal层的所有方法都是静态的,其中还包括一个静态的db连接对象:

public class BillsDal
{
    static IDbConnection _conn = ConnUtility.GateWayConntion;
    
    /// <summary>
    /// 获取指定业务订单的所有账单(by 商户code和订单号)
    /// </summary>
    /// <param name="bizOrderId">订单Id,唯一</param>
    /// <returns></returns>
    public static List<t_bills> GetOrdersBillList(string merCode, string bizOrderNo)
    {
        var obj = _conn.Query<t_bills>("select * from t_bills where merCode='" + merCode + "' and orderNo='" + bizOrderNo + "'");
        return obj.ToList();
    }
}

突然想到之前整理的blog《static,你还敢用吗?》,所以,不难分析出来原因:问题就出在这个静态的db连接对象_conn上,因为所有类的实例始终是用一个db连接,当并发出现时,又没有lock数据操作代码,那么,就很容易出现连接在未关闭时又要被建立并打开,这样就出现了db连接异常。
经模拟多线程来测试,的确如此。

问题即答案!修复这个bug的话,有如下2个方案:

  1. 如果仍然要保留这个static的_conn字段,就要用lock来锁住数据操作代码(GetOrdersBillList),以控制并发冲突
  2. 每次查询时用一个新的连接对象。

方案分析:第1种,涉及到对象只能在被释放(关闭)掉才能再次被使用(打开),性能低下,不可取。 第2种呢,其实在dal层,绝大多数的程序猿都是按照每一个数据操作只用一个db连接的方式来编码的。 由于大家一般不会把dal类的成员定义成static,所以,也就不会遇到这样的db连接异常。而我呢,倾向于用static方法,考虑到封装,就把这个db连接对象封装成静态字段了,反而忽视了静态数据成员带来的隐患——数据量小时几乎是暴露不出来问题,一旦数据量大起来,有了并发,就会出现资源被同时使用,这样的话,多个线程实例都要修改其状态时,就出现了并发异常。

由此来看,依然用static的话,就要把_conn当做只读的私有属性(不考虑代码味道):

static IDbConnection _conn
{
    get { return ConnUtility.GateWayConntion; }
}

这样,当每次访问这个属性时,都会返回一个新的连接对象。
再次模拟多线程测试,ok!

相关文章

  • static,你还敢用吗?(二)

    为了压系统,昨天小组在测试环境模拟了一大批订单数据。今天上午查看记录的账单计息日志,发现了一大堆的MySqlExc...

  • 不花钱的5种保险

    你敢用吗? 忍心用吗?

  • 素纹

    素纹纸帕,你敢用吗?哈哈哈

  • 你敢用超声刀吗

    晚上接儿子,电梯里遇到楼下的一位妈妈。脸有点肿,不敢大笑,面色发黑。她儿子一直再逗她,俩个人一句一句地逗着乐。我好...

  • 我敢写,你敢用吗?

    他身穿一身洁白的纯手工定制西装,整件衣服干干净净,没有一丝折痕。手捧一捧百合花,周围点缀着满天星,用绿色的丝带系成...

  • 滴滴敢用吗。

    关于滴滴司机奸杀女乘客的新闻,相信大家看过的比我多 我就不多说了。 但是网上又有了一种不一样的声音。 “女孩子,衣...

  • static作用与用法

    目录一、static变量二、static方法三、static代码块四、static class static表示“...

  • cas底层原理

    CAS 你知道吗? public class CASDemo { public static void mai...

  • 这样的员工,你敢用吗?

    在终端零售中,有些店铺生意做得并不好,业绩差,商品卖不动,员工没激情……当你问他们为什么生意差时,他们往往只会回应...

  • 共享手纸来了你敢用吗?

    八年前很多人讲O2O,六年前开始讲云计算,五年前讲大数据,四年前讲VR/AR,这几年讲AI/共享经济; 2017年...

网友评论

  • 171d1907e6d8:你用这个标题来表达这个问题难免有些片面,任何工具和方法都没有绝对的利和弊的。
    buguge:只是提醒大家,在用一个技术点的时候要注意其利弊,不要盲目使用。:blush:

本文标题:static,你还敢用吗?(二)

本文链接:https://www.haomeiwen.com/subject/nmwzvttx.html