开发者社区> 问答> 正文

PG 批量写入数据报错?报错

C#环境下一次性写1万多条数据,调用数据库接口之后有时候会报出以下错误信息:


2015/10/19 18:56:04  Tried to add too many fields to a copy record with 1 fields
2015/10/19 18:56:05  Tried to add too many fields to a copy record with 3 fields
2015/10/19 18:56:05  Tried to add too many fields to a copy record with 4 fields
以上是调试信息的一部分,调用同样的接口写入同种类型的数据,报出的错误稍微不同,但是错误类型是一样的。


接口中的逻辑:

1.先创建临时表

2.使用PG的bulk copy将数据批量写入临时表

PG bulk copy 代码如下:

using (PostgreSQLCopyDataToTempTableHelper copyHelper = new PostgreSQLCopyDataToTempTableHelper(conn, "COPY TEMP_WRITEFIXPERIOD(nodetype, nodeid, dataid, recordtime, periodtype, sourcetype, datavalue, maxvalue, minvalue, avgvalue) FROM STDIN"))
            {
                if (!copyHelper.Initialize())
                    return copyHelper.ErrorCode;
                try
                {
                    for (int i = 0; i < logs.Length; ++i)
                    {
                        copyHelper.AddValue(logs[i].nodeType);
                        copyHelper.AddValue(logs[i].nodeID);
                        copyHelper.AddValue(logs[i].dataID);
                        copyHelper.AddValue(logs[i].recordTime);
                        copyHelper.AddValue(logs[i].periodType);
                        copyHelper.AddValue(logs[i].sourceType);
                        copyHelper.AddValue(logs[i].dataValue);
                        copyHelper.AddValue(logs[i].maxValue);
                        copyHelper.AddValue(logs[i].minValue);
                        copyHelper.AddValue(logs[i].avgValue);
                        copyHelper.AddEndRow();
                    }
                }
                catch (System.Exception ex)
                {
                    Plugin.GlobalInformation.LastErrorString = ex.Message;
                    return (int)ErrorCode.SPCommonError;
                }

                return copyHelper.CopyDataToTempTable();
            }



其中
copyHelper.Initialize()执行批量处理的初始化工作,代码如下:
public bool Initialize()
        {
            try
            {
                npgsqlCommand = new NpgsqlCommand(copyDataToTempTableQuery, npgsqlConnection);
                npgsqlCopySerializer = new NpgsqlCopySerializer(npgsqlConnection);
                npgsqlCopyIn = new NpgsqlCopyIn(npgsqlCommand, npgsqlConnection, npgsqlCopySerializer.ToStream);
                npgsqlCopyIn.Start();
                return true;
            }
            catch (System.Exception ex)
            {
                Plugin.GlobalInformation.LastErrorString = ex.Message;
                errorCode = (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
                return false;
            }
        }



copyHelper.CopyDataToTempTable()执行批量将数据写入临时表的操作,代码如下:
public int CopyDataToTempTable()
        {
            try
            {
                npgsqlCopySerializer.Flush();
                npgsqlCopyIn.End();

                return (int)DBInterfaceCommonLib.ErrorCode.Success;
            }
            catch (NpgsqlException ex)
            {
                try
                {
                    npgsqlCopyIn.Cancel("Undo copy"); 
                }
                catch (Exception ex2)
                {
                    Plugin.GlobalInformation.LastErrorString = "Failed to cancel copy: " + ex2.Message + " Copy failure: " + ex.Message; 
                    return (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
                }
                Plugin.GlobalInformation.LastErrorString = ex.Message;
                return (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
            }
        }



说明一下:这个批量写入的数据库接口也不是每次都报错,有时候一次都不报,有时候次次都报,搞不懂是什么原因,可以保证临时表中的字段数量和要写入的数据的字段是一样的。但是跟踪调试的时候发现临时表的字段会变化,原因不明,创建临时表的代码如下:
public const string createTempTableForWriteFixPeriodDatas = @"CREATE TEMP TABLE TEMP_WRITEFIXPERIOD ( 
                        nodetype integer NOT NULL,
                        nodeid integer NOT NULL,
                        dataid integer NOT NULL,
                        recordtime timestamp without time zone NOT NULL,
                        periodtype smallint NOT NULL,
                        sourcetype smallint NOT NULL,
                        datavalue bigint,
                        maxvalue bigint,
                        minvalue bigint,
                        avgvalue bigint
                        )";

向临时表中添加数据的代码:

调试的时候在这一步报错:

提示的异常是:“Tried to add too many fields to a copy record with 1 fields ”。
<div>
	调试发现,npgsqlCopyIn.FieldCount 理论上10,但是程序运行中不知道什么原因变成1
</div>

请各位大侠帮忙分析一下原因,小弟万分感谢。

展开
收起
爱吃鱼的程序员 2020-06-12 10:40:18 701 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    昨天试了一下,发现修改了CopyBufferSize之后不再报这个错误,暂时先这样吧。

    2020-06-12 10:40:35
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
SQL Sever迁移PG经验 立即下载
俞航翔|基于Log的通用增量Checkpoint 立即下载
PostgresChina2018_赖思超_PostgreSQL10_hash索引的WAL日志修改版final 立即下载