Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2945087
  • 博文数量: 199
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 4126
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-06 19:06
个人简介

半个PostgreSQL DBA,热衷于数据库相关的技术。我的ppt分享https://pan.baidu.com/s/1eRQsdAa https://github.com/chenhuajun https://chenhuajun.github.io

文章分类

全部博文(199)

文章存档

2020年(5)

2019年(1)

2018年(12)

2017年(23)

2016年(43)

2015年(51)

2014年(27)

2013年(21)

2011年(1)

2010年(4)

2009年(5)

2008年(6)

分类: C#/.net

2014-08-18 15:05:29

BufferedStream的作用是给另一流上的读写操作添加一个缓冲层,改进IO效率。但最近在使用Npgsql(内部使用BufferedStream包装了NetworkStream)的过程中,发现BufferedStream有2个严重的问题,或者可以说是Bug。

1)BufferedStream不能同时读写
BufferedStream同时提供了读和写的API(这可能也是Stream的悲哀,不像Java中严格区分读Stream和写Stream),但是却不能同时读写。通过反编译BufferedStream,发现其内部结构有点像是工作在半双工模式下的通信接口,可以交替读写,但这个交替读写是有Bug的。

BufferedStream内部只有一个缓冲区,由读写操作共用。
a)读的时候,如果发现缓冲区中有未写完的数据,则写完缓冲区中的数据到底层流并Flush。
b)写的时候,如果发现缓冲区中有未读完的数据,则通过Seek()回退掉未读完的数据。

这套逻辑看上去很美,但是并不是每个流都支持Seek(),比如NetworkStream。底层流是NetworkStream的情况下就可能会莫名其妙的地方报出 NotSupportedException异常。

那在使用BufferedStream时,确保读完再写可不可以?
有些应用场景这一招管用,但至少对Npgsql不行。Npgsql严格按照发请求,读响应的逻辑和服务端通信。但却忘了PostgreSQL中存在所谓的异步消息,PostgreSQL服务端可能会在通常的响应消息后面插入一个异步通知。如果响应消息和异步通知都被读入BufferedStream的内部缓冲区,但Npgsql在这一轮请求循环中,只读出了和请求对应的响应消息,那么下次发送请求时就会触发上面提到的NotSupportedException异常。

解决方法:
比较简单的解决方法是,使用2个BufferedStream对象包装同一个底层流,分别用于读和写。

2)Read()的不当阻塞

(v=vs.80).aspx

  1. int Read([In, Out] byte[] array, int offset, int count)
  2. 读入 array 中的总字节数。如果可用的字节没有所请求的那么多,总字节数可能小于请求的字节数;或者如果在可读取任何数据前就已到达流的末尾,则为零。
当count小于BufferedStream对内部缓冲区的大小(默认4K),并且底层流中的有效数据小于count时,会导致Read()方法无限阻塞。
这应该是个Bug,根据MSDN中Read()的API描述(和流的Read()方法的惯例),这时应该将底层流已有的数据返回。
阅读(5017) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

skykiker2015-05-27 22:24:56

ll1999ss:楼主能否详细描述下解决方案不?近期我的数据库在数据量较大时也频繁出现该问题,我加入代码就出现很多错误 

Public Function Read(<InAttribute> <OutAttribute> array As Byte(), offset As Integer, count As Integer) As Integer
        Dim instance As BufferedStream
        Dim array As Byte()
        Dim offset As Integer
        Dim&n

你可以参考 https://github.com/npgsql/npgsql/issues/252 中我写的那段代码 “This's a sample implement:”

回复 | 举报

ll1999ss2015-05-26 09:42:53

楼主能否详细描述下解决方案不?近期我的数据库在数据量较大时也频繁出现该问题,我加入代码就出现很多错误 

Public Function Read(<InAttribute> <OutAttribute> array As Byte(), offset As Integer, count As Integer) As Integer
        Dim instance As BufferedStream
        Dim array As Byte()
        Dim offset As Integer
        Dim&n