• DataReader不奇怪,该出手时就出手!


    夜里三点多,刚完成微博粉丝精灵V3.763的微博升级,上来看看,刚看到一篇文章:【原】关于使用DataReader的一个很奇怪的问题,不应该用DataReader?

    于是准备花点时间解答下,顺便为这个月增添一篇文章。

    关于DataReader,以前写过一篇文章,可参考:DataReader 链接关闭解惑篇 

    下面将对原文,解答两个问题:

    一: DataReader、DataTable、DataSet 的简单关系:

    这里先取原文的第一句话:.net读取数据集有两种方式:DataSet 和 DataReader

    解答:.net 的Command操作里,默认可以有三种返回:DataReader、DataTable、DataSet

    这三者的简单关系为:

    DataReader 快速只向前读的流,需要开发者自己去关闭流。

    DataTable 一个容器,把DataReeader读到DataTable容器后关闭流。

    DataSet 一个大容器,里面可放置多个DataTable。

    因此开发者,首先要明白这三者的简单关系,才不至于乱猜。


    二:数据库链接、链接池、close与dispose

    这里再取原文的第N句话:在sqlserver(2000)中查看进程,有非常多的sleeping进程,直到最后打开页面,提示超时,说连接池满

    解答:默认mssql的链接数是有限的,大体在100多个,简单的说你可以open 100多次而不关闭,超过后再open就会出现链接池不够的现象。

    这之间的简单关系为:

    第一次Open出链接时,连接数据库(由于是首次建立链接,需要初始化先多信息,就是传说的性能问题)

    然后你Close时,数据库断开链接,同时把链接状态改成sleep,但是不销毁(为了下次建立链接时省掉初始化,避免传说中的性能问题),这个不销毁的链接,放到一个池里面,被称之为链接池。

    如果你Dispose(),则会把链接从池里销毁,当然下次链接就会开始新的初始化。


    下面就会有很多种情况出现:

    情况一:一个线程的正常操作:

    如果使用时一个流程下来,是按顺序的open->close-open->close 状态,那么始终只用到一个链接(从连接池里进进出出),基本没有过多的初始化问题,传说性能好。

    情况二:多个线程的不正常操作:

    如果你一个链接,在Open状态,这时候另一个线程也要打开链接,发现链接池没有时,就会重新到数据库建一个链接(又开始初始化,一堆信息,最后产生一个链接)。

    如果你所有的链接全在Open,不关闭,或者时间拖的很多,在其它线程要链接的时候,你的链接还没关闭,在产生100多个链接后,数据库最大数满了,就会出现“链接池已满”的情况。 

    情况三:多个线程的正常操作:

    如果你懂的每个链接打开后,都快速关闭,通常一个正常语句的操作时间在0.001-0.1秒左右,这样关闭的链接就回到池里,可以快速供给其它线程使用。

    这样,仅需要几十个链接,就可以循环的使用处理多线程问题。 

    简单的假设:

    如果一个操作open到close,用时0.1秒一次, 那么一个链接在1秒内可以处理10次操作。而100个链接最大数就可以支持1000次操作。

    简单的说就是1秒可以并发操作1000次以上,这对中小网站来说,处理是相当容易的事。

    而新手容易犯的错误,就是链接打开后,长时间的不关闭,最后导致在多线程的情况下,把数据库链接资源用尽了,出现了错误而不得知。 

    进一步的假设

    在很多的程序处理中,对数据库的操作时间,往往是不平均的,这就需要有点经验的程序开发者,花点时间,来搞好这最大并发问题,通常是:

    对长时间查询的,使用缓存(避免二次查询),或者集中使用队列(因为使用队列,就一个链接就可以搞定了,反正是开了读和关,然后下一个又是开了读和关,始终是一个链接),当然使用队列也要看情况。

    对于时间短的,直接处理就可以了。

    其实说白了,越往上,就越是“看情况处理”,没有啥定律,要是有,那就是数据库的最大链接数,无论你怎么耍流氓,反正你不能让它一次性给用完。 

    补充点:

    在sqlserver(2000)中查看进程,有非常多的sleeping进程,直到最后打开页面,提示超时,说连接池满,为什么,既然已经了很多 sleeping 的数据库连接, 为什么还会出现 不能连接数据库 的问题呢??

    答:

    对于ADO.NET,它有一种机制,来分析是使用产生新的会话还是直接从链接池中返回,例如,不同的数据库链接,它会产生新的链接,而不会从原有链接池里返回。

    而对于mssql,可能某种检测机制原因(不同的线程或进程链接),mssql分析后直接是为你产生新的链接,而不是从sleep状态的链接池返回,因此,原来的sleep无法复用,再次产生新的链接,就报链接池满了。

  • 相关阅读:
    iptables conntrack和state的区别
    shell中test命令方法详解
    Linux Shell 中各种括号的作用 ()、(())、[]、[[]]、{}
    mac terminal ssh连接linux乱码问题
    iptables 教程,iptables 详解,iptables 常见使用实例
    Redis实现主从复制(Master&Slave)
    TCP回射客户服务器模型(02 设置套接字选项、处理多并发)
    TCP回射客户服务器模型(01 socket bind listen accept connect)
    socket套接字(字节序、地址转换)
    TCP特点
  • 原文地址:https://www.cnblogs.com/cyq1162/p/2460964.html
Copyright © 2020-2023  润新知