您好,欢迎访问一九零五行业门户网

Error:7884,Severity:20,State:1

背景: 程序异常中断tcpprovider, error: 0 - an existing connection was forcibly closed by the remotehost.,手工执行查询没有问题,不过执行时间要几十秒。trace程序的执行,发现要数十分钟,经了解,原因在于程序使用了sqldatareader读取数据,并且在
背景:
程序异常中断“tcpprovider, error: 0 - an existing connection was forcibly closed by the remotehost.”,手工执行查询没有问题,不过执行时间要几十秒。trace程序的执行,发现要数十分钟,经了解,原因在于程序使用了sqldatareader读取数据,并且在读取的过程中进行了一系列数据处理,导致整个完成过程时间变得很长。由此怀疑是网络不稳定之类的因素导致处理过程中连接中断,协调之后改为datatable做一次性数据加载,程序调整之后,出现故障的频繁大大降低,但无法完全杜绝。
进一步检查,发现在sqlserver日志中,有如下错误:
error: 7884, severity:20, state: 1. (params:). the error is printed in terse mode because there waserror during formatting. tracing, etw, notifications etc are skipped.
这个错误与sys.messages中的标准描述不一样,在网上搜索没有找到合适的解决方案。
排查:
把查询的表专门导到一台服务器做测试,最终发现与一个nvarchar(max)列有关,随后想起在不久前,因为logreader出问题,把出问题的数据列从ntext改为nvarchar(max),于是专门测试这个修改,最终确定问题是这个修改导致。
(text/ntext列可能会导致logreaderagent出问题,这个遇到多次了,但没有明确的重现故障的方法,所以不讨论这个)
故障重现:
使用下面的t-sql创建测试表,数据,并修改ntext列为nvarchar(max)
-- ====================================== ================-- 创建测试表-- ======================================================use tempdb;goif object_id(n'dbo.tb_test', 'u') is not nulldroptable dbo.tb_test;gocreate tabledbo.tb_test(id intidentity primarykey,code varchar(50),datedatetime,value ntext);goinsert dbo.tb_testselect top(10000)code =right(10000000000 +abs(checksum(newid())) % (1000 * 2 ), 20),date= dateadd(day, checksum(newid()) % 100 , getdate() ),value =convert(char(36), newid() )from sys.all_columns a with(nolock),sys.all_columns b with(nolock);go-- ======================================================-- 修改 ntext 字段类型为 nvarchar(max)-- ======================================================alter tabledbo.tb_test altercolumn value nvarchar(max);go编写程序,查询数据,并且在查询完成前更改数据,这里用 powhershell 做测试# 连接字符串$connectionstring = data source=127.0.0.1;initialcatalog=tempdb;integrated security=sspi# 打开连接$sqlcnnectionquery = new-object system.data.sqlclient.sqlconnection -argumentlist $connectionstring$sqlcnnectionquery.open()# 查询数据$sqlcommandquery = new-object system.data.sqlclient.sqlcommand$sqlcommandquery.connection = $sqlcnnectionquery$sqlcommandquery.commandtext = select * from( select value, row_id = row_number()over( partition by code order by date desc) from dbo.tb_test with(nolock) )datawhere row_id = 1$sqlreader = $sqlcommandquery.executereader()# 修改数据$sqlcnnectionupdate = new-object system.data.sqlclient.sqlconnection -argumentlist $connectionstring$sqlcnnectionupdate.open()$sqlcommandupdate = new-object system.data.sqlclient.sqlcommand$sqlcommandupdate.connection = $sqlcnnectionupdate$sqlcommandupdate.commandtext = update top(1000) dbo.tb_test set value =convert(char(36), newid() ) where id in( select top 1000 id from dbo.tb_testorder by id desc )$updaterows = $sqlcommandupdate.executenonquery()$sqlcnnectionupdate.close()update $updaterows rows.#读取查询数据#读取过程中会出现错误# (sql 2008 r2 sp2): tcp provider, error: 0 - anexisting connection was forcibly closed by the remote host.# (sql 2008 r2 sp3): tcp provider, error: 0 - the specifiednetwork name is no longer available.at line:1 char:22read query data....$readrows=0while($sqlreader.read()) {$readrows+=1}read $readrows rows.# 关闭连接$sqlreader.close()$sqlcnnectionquery.close()
故障处理:
对于修改了数据类型的列,将数据重新更新就可以解决 问题(update 表 set 修改的列=修改的列)
这个问题测试了 sql server2008 到 2014,都存在问题。其中 sql server 2008 r2 sp3中测试,sql server日志中的错误信息有所不同,是:
error: 7886, severity: 20, state: 2.
a read operation on a large object failedwhile sending data to the client. a common cause for this is if the applicationis running in read uncommitted isolation level. this connection will beterminated.
其它类似信息

推荐信息