捕抓数据库偶发性异常,让执行计划更加健壮原创
金蝶云社区-山抹微云
山抹微云
5人赞赏了该文章 693次浏览 未经作者许可,禁止转载编辑于2020年05月11日 19:47:34

  执行计划 业务对象很好用,能提高效果。在这方面,最近遇到个问题,有一个客户上了云,该云环境偶尔波动,大概两周三次数据库连接不上,错误信息如下

  “执行计划调用时间: ,在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。 未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。”

    “执行计划调用时间:,执行出错,出错时间:; 错误信息:远程服务器返回错误: (500) 内部服务器错误。”

导致执行计划有问题,日志库里的T_BAS_SCHEDULELOG 表都有记录系统标准执行计划于二开执行计划都有记录错误,但是二开的插件遇到该错误为 任务状态转为"异常",然后不会自动恢复异常(即时勾选了该选项)。这位客户造成了很大的困难。

     其实这类问题,在C#编程中,要使用try跟catch,配合得当,就是这个周期遇到了该错误没执行,下个周期能执行到就行,由于周期间隔短,客户会没感知到该异常。

    我写了个例子, 大概想法,是在后台数据库创建[Ldq_SZ]表,表中有1列为SZ,是自增列,插件先查询最大的SZ,然后再上循环100次,每次都加1,插入到表Ldq_SZ。创建表的代码如下

CREATE TABLE [dbo].[Ldq_SZ](

[SZ] [int] NOT NULL,

[DT] [datetime] NULL,

 CONSTRAINT [PK_Ldq_SZ] PRIMARY KEY CLUSTERED 

(

[SZ] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]


C#代码如下 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Kingdee.BOS.Contracts;

using Kingdee.BOS.App.Data;

using Kingdee.BOS.LogPlatform;

using Kingdee.BOS.ServiceHelper;

using Kingdee.BOS.Log;

using Kingdee.BOS.Core;

using Kingdee.BOS;

using Kingdee.BOS.DataEntity;

using System.Threading; 


namespace ldq_IScheduleService_CF

{

    public class ldq_IScheduleService : IScheduleService

    {

        public void Run(Context ctx, Kingdee.BOS.Core.Schedule schedule)

        {

            string sql = string.Empty;

            int SZ_max = 0;

            try

            {

                var max = DBUtils.ExecuteObject<Kingdee.BOS.Orm.DataEntity.DynamicObject>(ctx, " select max(SZ) as SZ from Ldq_SZ ");

                SZ_max = Convert.ToInt32(max[0]["SZ"]);

            }

            catch (KDException e)

            {

                return; 

            }      

            for (int K = 1; K <= 100; K++)

            {

                sql = String.Format(" insert into Ldq_SZ ( SZ , DT) select {0}, getdate() ", Convert.ToString(SZ_max + K));

                ldq_Execte(ctx,sql);

            }

        }


        public void ldq_Execte(Context ctx,  string sql)

        {

            Thread.Sleep(500);

            try

            {

                DBUtils.Execute(ctx, sql);


            }

            catch (KDException e)

            {

               

            }

        }


    }

}

其效果是, 大概把表 Ldq_SZ 删除了, 该执行计划的任务状态还是在"运行".

另外,SZ是主键,就算插入到重复的主键,也是够健壮的。


赞 5