数据访问超时问题的总结

我们经常会讨论到数据访问超时的问题,当数据库服务器在远程,而且该操作需要耗用较长的时间的时侯,程序经常性出现一些超时的问题。那么应该从几个层面来探讨这个问题呢

1. 首先,我们来了解一下SQL Server内部执行的时间(默认是无限期等待的,即无超时)

image

2.其次,我们要知道SqlConnection的ConnectionTimeout属性,默认为15秒。这是获取在尝试建立连接时终止尝试并生成错误之前所等待的时间

该值不能通过编程设置,而是直接在连接字符串中指定

3.比较关键的是,我们要知道SqlCommand的CommandTimeout属性,默认为30秒。获取或设置在终止执行命令的尝试并生成错误之前的等待时间

值 0 指示无限制,在 CommandTimeout 中应避免值 0,否则会无限期地等待执行命令

此属性是在执行命令或处理结果期间所有网络读取的累积超时。在返回第一行之后,超时仍然可能发生,但只包括网络读取时间,而不包括用户处理时间。

结合这三点,我做了一个例子。下面的存储过程是故意地阻塞2分钟。

CREATE PROC GetServerTime(@result DATETIME OUTPUT)
AS
WAITFOR DELAY '00:02:00'
SET @result=getdate()

下面是客户端代码

using System;
using System.Data.SqlClient;
using System.Data;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnection conn = null;
            try
            {
                using (conn = new SqlConnection("server=(local);database=northwind;integrated security=true;connection timeout=30"))
                {
                    //Console.WriteLine(conn.ConnectionTimeout.ToString());
                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandTimeout = 0;//这里设置为0,即取消了命令的超时限制
                        cmd.CommandText = "GetServerTime";
                        cmd.CommandType = CommandType.StoredProcedure;
                        SqlParameter param = new SqlParameter("@result", SqlDbType.DateTime);
                        param.Direction = ParameterDirection.Output;
                        cmd.Parameters.Add(param);
                        Console.WriteLine("开始工作:" + DateTime.Now.ToString());
                        cmd.ExecuteNonQuery();
                        Console.WriteLine("取得结果:"+param.Value.ToString());
                    }
                    conn.Close();

                }
            }
            catch (SqlException ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (conn != null && conn.State != ConnectionState.Closed)
                    conn.Close();
            }

            Console.Read();
        }
    }
}

 

4.当该代码放在中间层,我们这里用Web Service为例,看看是否有什么问题?

using System.ComponentModel;
using System.Data;
using System.Web.Services;
using System.Data.SqlClient;

namespace WebService1
{
    /// <summary>
    /// Service1 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        public string GetServerTime()
        {
            SqlConnection conn = null;
            string result = string.Empty;
            try
            {
                using (conn = new SqlConnection("server=(local);database=northwind;integrated security=true;connection timeout=30"))
                {
                    //Console.WriteLine(conn.ConnectionTimeout.ToString());

                    conn.Open();
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandTimeout = 0;
                        cmd.CommandText = "GetServerTime";
                        cmd.CommandType = CommandType.StoredProcedure;
                        SqlParameter param = new SqlParameter("@result", SqlDbType.DateTime);
                        param.Direction = ParameterDirection.Output;
                        cmd.Parameters.Add(param);
                        cmd.ExecuteNonQuery();
                        result= param.Value.ToString();
                    }
                    conn.Close();

                }
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                if (conn != null && conn.State != ConnectionState.Closed)
                    conn.Close();
            }

            return result;
        }
    }
}

我们用客户端调用该web server,但仍然会超时。同样的代码,为什么会产生不一样的结果呢?

还要注意的一个地方是调用web service的客户端代理的超时设置。准确地说,大部分web service的代理类都是继承自WebClientProtocol类的。这个类有一个属性:timeout

http://msdn.microsoft.com/zh-cn/library/system.web.services.protocols.webclientprotocol.timeout.aspx

指示 XML Web services 客户端等待同步 XML Web services 请求完成的时间(以毫秒计)。默认值为 100000 毫秒。(即100秒)

如果将 Timeout 属性设置为 Timeout..::.Infinite,则指示该请求无超时。即使 XML Web services 客户端可以将 Timeout 属性设置为无超时,Web 服务器仍可以在服务器端使请求超时

 

ASP.NET的程序默认的执行超时时间为110秒,这是通过web.config文件中的一个属性设置的。就是下面这个executionTimeout.单位为秒,默认为110.以前是90.

image

image

注意,该属性只有当debug=false才生效

posted @ 2008-08-12 15:56  陈希章  阅读(3749)  评论(0编辑  收藏  举报