Keep thinking, Keep Studying。

一个简单的性能测试案例分享-“生成重复采购单号”问题的解决

上一篇 / 下一篇  2007-03-17 17:55:50 / 个人分类:学习笔记

一,问题发生原因:
New PO单(采购单),填写信息以后, 点击保存,系统生成流水号PO#,客户反应有时会产生重复的PO#。 (该问题属于历史遗留问题)

二,问题探索:
测试人员进行功能测试, 并没有这种现象的发生, 该问题在客户环境上出现频率也较低,
初步判定这是一个并发问题,


判定之后需要做的一件事情, 就是如何去重现这个问题, 以验证我们的判定是正确的:

1,  使用LoadRunner 模拟生成PO单的操作,并发点设置在Save 按钮处。

   经过尝试, LoadRunner对于Remoting 方式的程序支持程序不理想,无法进行新增PO的录制


2,  直接设置 PO主表的PO#,为 unique(不可重复),使用do{} while()等类似语句,尝试生成流水号并插入数据表,如果插入不成功会重新生成一遍插入。

这样做的问题是:

A,  会导致插入失败,提示信息容易导致客户不满,

B,  会导致一些用户执行时间过长, 影响效率,

C,  该办法只是最快解决问题的一个办法,为备用办法

3,  直接验证New PO功能所调用的SP ,验证其并发是否有问题

由于不知道有没有性能测试工具可以进行SP的并发测试, 考虑到了自己写测试程序, 生成多个线程,每个线程并发调用SP的形式来模拟SP的并发运行。

三,方案验证:
考虑到SP执行的时间比较短, 而生成线程是采用循环方式生成, 毕竟还是有先后顺序,为了使并发情况产生的更加明显, 特意让每一个线程都连续调用三次SP,(次数可以自己设置, 这里使用三次主要是考虑到生成的PO#也不要太多, 否则不容易看清楚),

界面元素:

User Number: 预计生成的线程个数。(Edit box)
Purno:最终生成的PO#(ListView)
During:Sp执行需要花费的时间,顺便检查线程阻塞情况。(ListView)


主要代码如下:

for(int i= 0; i < num; i++)
     {
      ThreadStart start = new ThreadStart(CreatePONumber);
      Thread th = new Thread(start);

      th.IsBackground = true;
      th.Start();
     }


CreatePONumber 为执行SP的函数,函数主要内容如下:

for(int i = 0; i < 3; i++)
    {
     DateTime startDate = DateTime.Now;

     object ōbj = cmd.ExecuteScalar();

     DateTime endDate = DateTime.Now;

     if (obj != null && obj != DBNull.Value)
     {
      ListViewItem lvi = new ListViewItem();
      lvi.Text = obj.ToString();
      lvi.SubItems.Add(endDate.Subtract(startDate).TotalMilliseconds.ToString());

      listView1.Items.Add(lvi);
     }


运行结果: 果然生成了重复的 PO#,并且重复的形式如下:

            19998,19999, 20000,20002,20002,20003 (在20000之后没有出现20001)

            重现成功!

          

四,解决问题:
经过分析, 发现是因为SP中的 一个语句顺序错误引起的, 错误语句流程如下:

   Update SysData set PoNo=PoNo+1  where sysid='ABS' 

   select PoNumber=PoNo from sysdata where sysid='ABS'

   - 说明: PO最大number号会保存在 SysData 表中。 SP中先Update 了这个Data 表中的PO#, 让PO+1,再查询这个最新的PO#, 最后我们会将查询到的PO新number, insert 到PO主表中


分析之后发现,在进行update的时候因为会有排它锁, 在进行并发操作时, 前一个线程还没有来得及进行select语句, 后一个线程又开始update了, 于是会造成 前后两个线程都select 了后面的那个Po Number,导致出现PO number重复


修改之后部分语句如下:


BEGIN TRAN

       DECLARE @PONumber int


       select @PoNumber=PoNo from sysdata (tablockx) where sysid='ABS'

    IF @@ERROR <> 0 GOTO ErrorHandle

       SET @PONumber = @PONumber + 1

    IF @@ERROR <> 0 GOTO ErrorHandle

       Update SysData set PoNo=PoNo+1  where sysid='ABS' 

    IF @@ERROR <> 0 GOTO ErrorHandle

       COMMIT  TRAN

       SELECT @PONumber AS PONumber

       RETURN

ErrorHandle:

       ROLLBACK TRAN

       SELECT PoNumber = 0

 

五,回测:
     经过回测,功能正常, 没有发现有重复PO出现, 且 SP执行耗用时间前后对比 差不多, 没有引发效率问题。


结束语:
     这是一个没有使用性能测试工具的简单性能测试实例, 这里分享给大家,希望可以对于各位今后的工作有所帮助。


相关阅读:

TAG: 学习笔记

xxh2gray的个人空间 引用 删除 xxh2gray   /   2012-05-18 16:24:50
不错,很好!
testingirl的个人空间 引用 删除 testingirl   /   2012-03-23 16:20:27
看不懂
引用 删除 ruyingsuixing   /   2007-06-06 20:25:21
值得学习!
 

评分:0

我来说两句

Open Toolbar