Остановка пула соединений Npgsql при соединениях MinPoolSize

Первый раз работал с Npgsql, хотя я занимался другим программированием на PostgreSQL. Npgsql 3.1.6, PostgreSQL 9.5. Visual Studio 2015 с.Net 4.5.1.

У меня есть строка подключения, которая выглядит следующим образом (одна и та же строка используется каждый раз, без изменений, для каждой попытки подключения к БД):

Сервер =dbserver;SearchPath= сеть; База данных =netinfo; ID пользователя =netuser; Пароль =netpassword; Порт =19491;CommandTimeout=300; Пул =true;MaxPoolSize=75

Это многопоточный сборщик данных C# для нашей сети. До 32 потоков работает на коллекторе. Каждый поток открывает соединение при необходимости, но одновременно использует только одно соединение. Соединение будет закрыто и повторно открыто потоком, если это необходимо. Я написал свой собственный пул соединений, и он работал; откройте связку в начале, вытащите открытое соединение из ConcurrentQueue, используйте его, а затем верните в очередь. В очереди проведено 16 открытых соединений. Чревато опасностью, если не сделано правильно, но это сработало. Во время проверки кода коллега включил меня в пул соединений Npgsql, поэтому я пытаюсь его использовать.

я собираюсь System.InvalidOperationException, "The connection is not open" когда я достигну команды ОБНОВИТЬ (dbCommand.ExecuteNonQuery()); Я не верю, что сама команда важна - это только та, которую она поражает. Я замечаю, что на сервере БД netstat показывает MinPoolSize+1 открытый сокет. В приведенной выше строке подключения он не определен, поэтому MinPoolSize равен 1. Я вижу два сокета в netstat. Если я установлю MinPoolSize на 16, я увижу 17 сокетов. Похоже, Npgsql открывает минимальный размер пула, а затем создает исключение InvalidOperationException при следующем подключении. Но он должен иметь до 75 доступных соединений и блокировать, когда они недоступны. Это не.

Максимальное количество соединений на моем сервере PostgreSQL составляет 100; Я не близко к этому порогу.

Это работает, когда я использую свой самописанный метод совместного использования пула, поэтому нет проблем с кодом, который выполняет запросы. Это просто, как я получаю текущее соединение.

Мысли? В поле зрения? Спасибо!

Изменить: согласно запросу.,, это немного долго, но это показывает пару смежных условных обозначений для идеи потока.

lock (ArpTableLocks.GetLock(nd.IdNd + " " + idMi + " " + idIf))
{
    if (_arpTableList.Get(nd.IdNd, idMi, idIf) == null)
    {

        // No device/MAC/IP/intf entry in DB, add one
        var dbConn = new NpgsqlConnection(DBStrings.connectionString);

        var dbCommand = new NpgsqlCommand(DBStrings.sqlARPTableInsert, dbConn);
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_mi", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_nd", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_if", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters["@id_mi"].Value = idMi.ToString();
        dbCommand.Parameters["@id_nd"].Value = nd.IdNd.ToString();
        dbCommand.Parameters["@id_if"].Value = idIf.ToString();
        var dbRead = dbCommand.ExecuteReader();
        dbRead.Read();
        idAt = dbRead.GetInt32(0);
        var arpTableListEntry = new ArpTableEntry
        {
            Id = idAt,
            IdNd = nd.IdNd,
            IdMi = idMi,
            IdIf = idIf
        };
        _arpTableList.Add(arpTableListEntry);

        dbRead.Close();
        dbConn.Close();

    }

}
idAt = (_arpTableList.Get(nd.IdNd, idMi, idIf).Id);

lock (ActiveArpTableLocks.GetLock(nd.IdV + " " + idAt))
{
    if (_activeArpTableList.Get(nd.IdV, idAt) == null)
    {
        var dbConn = new NpgsqlConnection(DBStrings.connectionString);

        NpgsqlCommand dbCommand = new NpgsqlCommand(DBStrings.sqlActiveARPTableInsert, dbConn);
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@seen", NpgsqlTypes.NpgsqlDbType.Timestamp));
        dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString();
        dbCommand.Parameters["@id_at"].Value = idAt.ToString();
        dbCommand.Parameters["@seen"].Value = ae.TimeSeen;
        dbCommand.ExecuteNonQuery();

        // Insert a history record
        dbCommand = new NpgsqlCommand(DBStrings.sqlHistoryARPTableInsert, dbConn);
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@firstseen", NpgsqlTypes.NpgsqlDbType.Timestamp));
        dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString();
        dbCommand.Parameters["@id_at"].Value = idAt.ToString();
        dbCommand.Parameters["@firstseen"].Value = ae.TimeSeen;
        dbCommand.ExecuteNonQuery(); // Exception thrown here

        dbConn.Close();

        Interlocked.Increment(ref _arpEntryAdded);

    }
    else
    {

        // DB has an active ARP table entry, so update its seen time.
        var dbConn = new NpgsqlConnection(DBStrings.connectionString);

        NpgsqlCommand dbCommand = new NpgsqlCommand(DBStrings.sqlActiveARPTableUpdateSeen, dbConn);
        dbCommand.Parameters.Add(new NpgsqlParameter("@seen", NpgsqlTypes.NpgsqlDbType.Timestamp));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_v", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters.Add(new NpgsqlParameter("@id_at", NpgsqlTypes.NpgsqlDbType.Integer, 4));
        dbCommand.Parameters["@seen"].Value = ae.TimeSeen;
        dbCommand.Parameters["@id_v"].Value = nd.IdV.ToString();
        dbCommand.Parameters["@id_at"].Value = idAt.ToString();
        dbCommand.ExecuteNonQuery();

        dbConn.Close();

        // Remove from activearptable hashtable
        _activeArpTableList.Delete(nd.IdV, idAt);
        Interlocked.Increment(ref _arpEntryUpdated);

    }
}

0 ответов

Другие вопросы по тегам