zoukankan      html  css  js  c++  java
  • MSSQL连接字符串,你真的清楚吗?


        几年前当我第一次面试时,考官发现我是个新手于是他让我写个连接字符串,虽然当时就知道X种连接字符串的写法,但是当时却没能写对一个,工作多年后我仍然不能写一个正确的连接字符串,但我知道打发新人时,让他写连接字符串是个不错的方法.

       以下是一个常用的ADO.NET 连接MSSQL的字符串
      "Data Source=.;Initial Catalog=MyDBA;Integrated Security=SSPI"
      在IIS 环境下 我们也许会这么写
      "Data Source=.;Initial Catalog=MyDBA;User Id=用户名;pwd=一般人我不告诉他;"
      
    使用高效的协议(虽然我们一直这么做,但一直没注意)
      首先要搞清楚我们是使用什么方式与MSSQL数据库服务沟通的,当然微软产品的好处是即使你不知道,他也会帮你选择一个最合适的方式,在IIS跟MSSQL同台服务器的情况下,默认使用共享内存.
    图1)

    要确认ADO.Net建立的是什么方式的连接可以通过,企业管理器中->管理->进程信息

    可以看到ADO.NET提供程序,.Net SqlClient data Provider

    使用LPC(本地调用,即共享内存)

     如果你把上面的连接字符串改成"Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI"
    注意我的电脑上安装了多个SQL2000实例,其中一个为SQL2K ,使用上面的连接字符串打开一个连接后,再查看进程信息,发现LPC 现在变成了Tcp/IP(注意是.Net SqlClient Data provider对应的行)这个表明现在你启用了TCP/IP来连接数据库,
    当然在IIS跟SQL同服务器的情况下建议你使用LPC,这样速度跟性能都比较优越.

    在连接字符串中使用端口
    一般异地连接时我们多使用tcp/ip协议,默认端口是1433,有时候你可能想改变这个端口,为此你需要使用"服务器网络实用工具"(在开始->Microsoft SQL Server下面),在里面配置Tcp/ip 协议并指定一个新的端口.

        这里指定了8888 为实例SQL2K的新端口,注意请不要将"隐藏服务器(H)"选择中,保存更改后就可以下面的连接字符串进行连接了"Data Source=127.0.0.1,8888;Initial Catalog=MyDBA;User ID=sa ",同样在进程信息里你能看到ADO.NET的一条用户名为sa的TCP/IP连接.但是当我们试图从远程连接这台SQL服务器时通常会出现问题,一般服务器上都有防火墙,而且只开放web,ftp,远程桌面等几个有限的端口,而你上面指定8888未在其列,因此当你在异地来连接数据库时会报错,(另外连接字符串如"Data Source=60.188.86.49,8888;Initial Catalog=MyDBA;User ID=sa;pwd=" ,中需要注意的是端口号跟IP或域名之间用逗号","隔开)为解决此问题你需要在防火墙中开放8888端口.
       完成后,你可以使用上面IP+端口的形式访问数据库了,不过你在使用以上连接字符串前,是否尝试过类似
    "Data Source=www.wow52.cn\SQL2K;Initial Catalog=MyDBA;User ID=sa;pwd=;" 形式的连接字符串呢,这里采用域名加实例名的样子,可能你尝试了下发现行不通,反正我当时是这样做过但发现不行,虽然感觉这个形式很直观,但是怎么就不行呢?
       当然如果你细心的话,回过头去看上文有个"Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI"
    形式的连接字符串,这个是IP+实例的形式,本质上已经是域名+实例的形式了,那么为什么不行呢?问题同样是出在防火墙上面,不过这次你需要开放的是一个UDP端口1434以给运行SQL Server 解析协议 (SSRP)的服务使用,当你使用域名+实例名访问时,解析服务会解析成 IP+端口的形式进行数据库连接. 现在你通过企业管理器中的进程信息查看时,可以看到一个TCP/IP连接了,
    SQL Server 解析协议 在SQL2005中被SQL Server Browser 取代,在需要进行远程连接,并且采用域名或IP+实例名的形式时,你需要启动这个服务,并且在防火墙中开放相应端口. 最后关于端口部分,还有一点是SQL2000,跟SQL2005多支持动态端口,也就是把端口设置为0(SQL2005 具体参考配置工具),这个时候为使数据库能在异地正确访问,你需要在防火墙中以添加程序的形式把sqlserver.exe添加进去,如实例SQL2k的程序位置是
    D:\Program Files\Microsoft SQL Server\MSSQL$SQL2K\Binn\sqlservr.exe,具体取决于你的安装位置,SQL2005可以在服务器网络配置工具里查看. 除了需要添加sqlserver.exe程序外,你还需要开放1434 UDP端口,或者在使用SQL2005时把C:\Program Files\Microsoft SQL Server\90\Shared\sqlbrowser.exe 添加到防火墙里, sqlbrowser.exe 使用的也是1434 UDP端口.

    以上所讲述在我的MSSQL2000里都不行!
      

       如果你不幸遇到这样的情况,最重要的一点是查看你sql的版本,请在查询分析器里运行 Select @@Version,或者看帮助菜单中的"关于..." 如果版本不是8.00.2039(现在说的是SQL2000),那么赶紧升级把,下个SQLSP4来打上.
    如果打上补丁还无济于事,那么请确定你在SQL Server网络实用工具中启用了TPC/IP协议,并在防火墙中开放了相关端口.

    连接字符串中的一些属性
     
      Connection lifetime 连接生存时间,默认为0,表示无限长,单位为秒.在SQL集群环境中我们才设置为具体的数值.

      Connection timeout 连接生成时间,默认为15秒,通俗的讲当你conn.Open等15秒后还没连接成功,那么就会抛出一个连接超时的错误,这也是为什么其他错误来的那么突然,而数据库连接超时错误,非要你等15秒的原因了.

      Pooling 是否使用连接池, 默认是起用的,使用Pooling=false来禁止.

      Min Pool Size,Max Pool Size 默认情况下最小是0,最大是100.

      关于pooling属性在上面所有的连接字符串中多是默认开启的,连接池能有效的提高数据库访问性能,因为创建一个连接需要消耗很多资源,尤其是进行异地访问时(一般指局域网,最好不要进行跨internet的数据库访问)更加如此,因此你在多数情况下不需要显式的禁止(也许你没在意微软一直帮你开通着), 事实上在你使用 conn.open() ,conn.close() 多少数情况下不是真的打开一个连接,而是向连接池中取一条可用连接,跟归还一条连接,conn.open操作只有在池中没有可用连接时才会创建一条连接,当然如果池中可用接数目达到Max Pool Size时,他将不再创建新的连接,而是等待一条可用连接的到来,这个时间是Connection timeout. 当然你的conn.Open操作涉及的连接池,取决于你的连接字符串,比如:
    "Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI"


    "Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI
    ;" ,注意后面多了";"
    会开启两个独立的连接池,ADO.NET 判断字符串是否相同的依据是对字符串进行2进制的比较,所以任何变动(空格,大小写)都会被判断为不同的连接字符串.
    有如下代码
    -----------------------------------
    string strConn="Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI
    ;";
    for(int i=0;i<10;i++){
      SqlConnection conn=new SqlConnection(strConn);
      conn.Open();
      conn.Close()
    }

    string strConn="Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI
    ;";
    for(int i=0;i<10;i++){
      strConn +=" "; //空格
      SqlConnection conn=new SqlConnection(strConn);
      conn.Open();
      conn.Close()
    }
    两段代码分别运行,看企业管理器->管理->进程信息(请刷新先) ,可以看到前面的只启用了一个进程,而后面的则启用了10个进程,每个进程对应一条连接.前一段代码10个open +close()操作使用的是同一个连接池中的同一个连接,而后一个则开启了10个连接池,每个连接池中有一个连接.

    再看下面的代码
                for (int i = 0; i <= 10; i++)
                {
                    Thread t = new Thread(new ThreadStart(Command));
                    t.Start();
                }
    ---------------------
    //Command定义
    private void Command(){
    string strConn="Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI
    ;";
      Sqlconnection conn=new SqlConnection(strConn);
     SqlCommand cmd=new SqlCommand("一个运行比较长的查询",conn);
      conn.Open();
      cmd.ExecuteNonQuery();
      
      conn.Close()
    }
      运行后可以看,企业管理器->管理->进程信息里会开启10个到MyDBA数据库的连接进程,但是需要注意的是,这10个进程是属于同个连接池的,为了证明这一点你可以将上面的连接字符串改为
     private void command(){
    string strConn="Data Source=127.0.0.1\SQL2K;Initial Catalog=MyDBA;Integrated
    Security=SSPI
    ;Max pool Size=5;"; //加了Max Pool Size=5;
      SqlConnection conn=new SqlConnection(strConn);
     SqlCommand cmd=new SqlCommand("一个运行比较长的查询",conn);
      conn.Open();
      cmd.ExecuteNonQuery();
      
      conn.Close()
    }
    结果可以看到他只开启了5个到MyDBA数据库的连接,这证明他们是同个连接池的.当然这里能成功演示的前提是,cmd执行的任务时间要在15秒内,不然会出现后5个线程连接超时,另外使用SQL2000 的跟踪工具(SQL2005中是,SQL Server Profiler)是你观察以上实验的一个绝好的工具!

  • 相关阅读:
    《MySQL必知必会》第六章:过滤数据
    《MySQL必知必会》第七章:数据过滤
    《MySQL必知必会》第五章:排序检索数据
    Java高级特性:clone()方法
    Java基础知识详解:abstract修饰符
    Java虚拟机:虚拟机内存区域和内存溢出异常
    Java虚拟机:源码到机器码
    Java虚拟机:本地方法栈与Native方法
    [LeetCode] 1481. Least Number of Unique Integers after K Removals
    [LeetCode] 331. Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/wdfrog/p/1205885.html
Copyright © 2011-2022 走看看