将大对象插入Postgresql会返回53200 Out of Memory错误

时间:2013-01-24 20:03:51

标签: database memory blob postgresql-9.1 npgsql

Postgresql 9.1 NPGSQL 2.0.12

我想要存储在postgresql数据库中的二进制数据。大多数文件加载正常,但是,大型二进制(664 Mb)文件导致问题。当尝试通过Npgsql使用Large Object支持将文件加载到postgresql时,postgresql服务器返回“内存不足”错误。

我目前正在使用4Gb RAM的工作站上运行它,2Gb可用,而postgresql在空闲状态下运行。

这是我正在使用的代码,改编自PG Foundry Npgsql User's Manual

using (var transaction = connection.BeginTransaction())
{
    try
    {
        var manager = new NpgsqlTypes.LargeObjectManager(connection);
        var noid = manager.Create(NpgsqlTypes.LargeObjectManager.READWRITE);
        var lo = manager.Open(noid, NpgsqlTypes.LargeObjectManager.READWRITE);
        lo.Write(BinaryData);
        lo.Close();
        transaction.Commit();
        return noid;
    }
    catch
    {
        transaction.Rollback();
        throw;
    }
}

我已经尝试将postgresql的内存设置从默认值修改为调整所有值的方式:

  • shared_buffers
  • work_mem
  • maintenance_work_mem

到目前为止,我发现postgresql是一个很棒的数据库系统,但这是目前的一个显示阻止,我似乎无法将这个大小的文件放入数据库。如果我能帮忙的话,我真的不想处理手动将文件分成块并重新创建客户端。

请帮忙!?

2 个答案:

答案 0 :(得分:2)

我认为答案似乎是使用字节数组的块迭代地调用LargeObject类的Write()方法。我知道我说我不想处理数据分块,但我真正的意思是将数据分块为单独的LargeObjects。这个解决方案意味着我将数组块化,但它仍然作为一个对象存储在数据库中,这意味着我不必跟踪文件部分,只需要跟踪一个oid。

 do 
 {
   var length = 1000;
   if (i + length > BinaryData.Length) length = BinaryData.Length - i;
   byte[] chunk = new byte[length];
   Array.Copy(BinaryData, i, chunk, 0, length);
   lo.Write(chunk, 0, length);
   i += length;
 } (i < BinaryData.Length)

答案 1 :(得分:1)

尝试减少max_connections的数量,以便为需要执行700MB操作的少数连接保留内存。将work_mem(每次操作可用的内存)增加到1GB。试图将700MB塞入一个领域听起来很奇怪。

将shared_buffers大小增加到4096MB。