最近一直在搞mongodb 文件服务器大量文件并发上传测试,在官方文档发现mongo是线程安全的,支持单一连接下的并发操作。印象ADO.NET 似乎不支持单一连接并发。于是,测试一下来证实这个疑虑。(前两篇小记一直纠结mongodb吃内存导致并发文件上传变慢问题,经过这两天测试,发现文件并发上传越来越慢的瓶颈是磁盘的IO读写的瓶颈)

以10W条/20W条 记录写入测试,下面是测试结果

操作

10W w/s

20W w/s

操作方式

备注

1

79.958

163.396

主线程 有池 单连接 单打开

单打开指的一次open close 内执行所有写入操作

2

79.958

164.412

主线程 有池 单连接 多打开

多打开指的写入一次就open close一次





总结:可以看出有池的情况open close基本没有性能消耗。

MSDN官方解释,池的效果在minpoolsize不为零的情况,

总保持相应数量的活动连接,当Open的时候实现直接用了活动连接,

而Close操作并没close,只是又将活动连接放回池里。

3

79.13

163.396

主线程 无池 单连接 单打开


4

290.334

620.694

主线程 无池 单连接 多打开






总结:无池的情况下,open close非常消耗性能,由于没池每次Open

Close 都要打开关闭连接 ,所以效率没有池高。

5

49.13

142.33

单线程 无池 单连接 单打开

异步执行反而快了?测了几次都这个结果

6

326.495

865.44

单线程 无池 单连接 多打开







7

137.985


有池 单连接 单打开 10线程并行写入  写入锁

Ado.net 不支持单连接并行写入 通过线程锁控制实现

8

141.464


有池 单连接 多打开 10线程并行写入  写入锁

Ado.net 不支持单连接并行写入 通过线程锁控制实现





总结:单连接通过写入锁控制多线程写入速度明显慢了很多,

单连接并不适合并发写入操作。

9

18.943

37.815

有池 10连接并行 单打开 

相当于操作1 ----  10个单连接 单打开 的并行操作

10

19.658

41.793

有池 10连接并行 多打开 

相当于操作1 ----  10个单连接 多打开 的并行操作





总结: 多线程并行多连接的操作效果还是很理想的,发挥了多线程任务的优势。Connection是非线安全的,也就是说最好为每个线程单独创建一个数据库连接实例是最理想的。

 

 

 

 

 

可以确定的是ado.net connection 是非线程安全的 一个连接下一次open close 过程不允许并发,并且多次open close并发会相互冲突 (想并发只能通过锁来控制了,但这个不用想肯定效率不高)。

      而mongodb 则在这方面具有优势, mongo是线程安全的。一个连接下是允许并行写入操作的,同样mongodb 可以多连接并发,然后每个连接下又可以多并发写入操作,这样每秒并写入记录数可以更高。mongodb的池,是预先创建指定数量的闲置连接,用到其中的连接的时候,该转为活动状态。经过这两天测试,mongodb的单连接的并行写入效率没有并行多连接写入的效率高。推测mongodb的单连接并行写入也采用了写锁或者队列,效率上可能低于多连接操作。因此在合理的并行线程内,合适的并行连接数写入很重要。

由此可见,不同的数据库池的设计理想有所不同。

而ado.net 写入并发实现只有下面两种合适的
一 有池-单连接 单打开  并发写入(引及写入锁) (锁的引入,反而导致速度下降,这个方案排除了)

二 无池-并发多连接   单打开                   这种不推荐 
二 有池-并发多连接   单打开/多打开          目前,测试只有这种情最理想

另外建议连接池的minpoolsize 要设置(不设置或设置为零,会在一定时间内关闭池内所有连接)但不要设置太高,否则会占用太多资源。详细可查看MSDN介绍。

在微软的Petshop以及很多开源项目曾经看到的SQLHelper此类的数据库存操作类大都是静态的? 为什么呢,因为静态方法在不引用静态字段的前提下是线程安全的。静态字段是多线程共享的,而静态方法在每个线程是都有一个副本,只要静态方法不调用静态字段则是线程安全的,因此我们看到为何SQL 单连接的情况都是使用静态方法,可以防止单连接并发操作。