Oracle соединения не закрываются - PullRequest
4 голосов
/ 20 января 2012

У нас есть приложение ASP.NET, которое подключается к базе данных oracle с помощью odp.net.

В последнее время у нас начались проблемы с производительностью. Похоже, что соединения Oracle не закрываются и в конечном итоге накапливаются, пока не произойдет сбой нашего сайта.

В качестве первого шага мы сделали обзор кода и убедились, что закрываем все открытые соединения после выполнения.

OracleConnection cn = Helpers.ConnectToDB();
    try
    {

        cn.Open();
        //do somtehing
    }
    catch (Exception ex)
    {
        //log error
    }
    finally
    {
        cn.Close();
        cn.Dispose();
    }

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

Вот журнал подключений за вчерашний день:

TO_CHAR(DATE_TIME,'DD/MM/YYYY   MACHINE STATUS  CONNECTIONS 
19/01/2012 14:40:03 WORKGROUP\OTH-IIS-1 ACTIVE  1   
19/01/2012 14:38:00 WORKGROUP\OTH-IIS-1 ACTIVE  2   
19/01/2012 14:35:57 WORKGROUP\OTH-IIS-1 ACTIVE  2   
19/01/2012 14:34:55 WORKGROUP\OTH-IIS-1 ACTIVE  28  
19/01/2012 14:33:54 WORKGROUP\OTH-IIS-1 ACTIVE  26  
19/01/2012 14:31:51 WORKGROUP\OTH-IIS-1 ACTIVE  34  
19/01/2012 14:30:49 WORKGROUP\OTH-IIS-1 ACTIVE  96  
19/01/2012 14:29:47 WORKGROUP\OTH-IIS-1 ACTIVE  73  
19/01/2012 14:28:46 WORKGROUP\OTH-IIS-1 ACTIVE  119 
19/01/2012 14:27:44 WORKGROUP\OTH-IIS-1 ACTIVE  161 
19/01/2012 14:26:43 WORKGROUP\OTH-IIS-1 ACTIVE  152 
19/01/2012 14:25:41 WORKGROUP\OTH-IIS-1 ACTIVE  109 
19/01/2012 14:24:40 WORKGROUP\OTH-IIS-1 ACTIVE  74  
19/01/2012 14:23:38 WORKGROUP\OTH-IIS-1 ACTIVE  26  
19/01/2012 14:22:36 WORKGROUP\OTH-IIS-1 ACTIVE  2   
19/01/2012 14:21:35 WORKGROUP\OTH-IIS-1 ACTIVE  2

Точка сбоя произошла в 14:27:44, и после перезапуска приложения соединения начали прерываться.

строка подключения, которую мы используем:

<add name="OracleRead" connectionString="Data Source=xxx;User Id=yyy;Password=zzz;Max Pool Size=250;Connection Timeout=160;" providerName="Oracle.DataAccess"/>

Так в чем здесь проблема?

Нужно ли нам определить или изменить одно из следующих свойств:

Connection Lifetime, Decr Pool Size, Max Pool Size, Min Pool Size?

Какие рекомендуемые настройки в этой ситуации?

Ответы [ 4 ]

3 голосов
/ 22 февраля 2012

Вам необходимо явно удалить все объекты Oracle.DataAccess, включая Connections, Commands и Parameters.

См. Пример кода в комментариях здесь:

https://nhibernate.jira.com/browse/NH-278

Пара других заметок:

  • Предпочитайте ключевое слово using, поскольку это гарантирует удаление даже в исключительных случаях.
  • Объект параметра ODP Paramter является особым (по сравнению с обычным контрактом параметров ADO.NET), поскольку он также требует явного удаления (тогда как, например, версия SQL Server этого не делает)
2 голосов
/ 24 мая 2013

Я знаю, что этот вопрос довольно старый, но я нашел решение, которое, кажется, работает для меня.

Мое решение - вызвать обработчик ASHX, который затем возвращает изображение, в среднем эта служба вызывается между 10-14 разами за загрузку страницы определенной страницы.

Я использую пространство имен ODP.NET Oracle.DataAccess.Client V4.112.3.60 для 64 бит.

У меня есть весь мой код в использовании операторов (обфускация здесь):

using (OracleConnection conn = new OracleConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["####"].ConnectionString))
{
    using (OracleCommand cmd = new OracleCommand(query, conn))
    {
        OracleParameter p = new OracleParameter("####", OracleDbType.Varchar2, 10);
        p.Direction = ParameterDirection.Input;
        p.Value = val;

        cmd.Parameters.Add(p);
        conn.Open();
        using(OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            if (reader.HasRows)
            {
                while (reader.Read())
                {

                    OracleBlob lob = reader.GetOracleBlob(0);
                    //OracleLob lob = reader.GetOracleLob(0);
                    srcImage = new Bitmap(lob);
                }
                newImage = resizeImage(srcImage, new Size(120, 150));
                newImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            else
            {
                srcImage = new Bitmap("Images/none.jpg");
                newImage = resizeImage(srcImage, new Size(120, 150));
                newImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                ProcessError(ref context, 500);
            }
        }
        p.Dispose();
    }
}

Я пробовал много вещей:

  • Проверка других соединений, открытых одновременно
  • Переписал элемент управления источником данных SQL, чтобы у меня было больше контроля над соединениями
  • Использование System.Data.OracleClient)

Но когда дело дошло до пошагового выполнения кода, я обнаружил, что иногда код не достигает конца используемого блока, и следующий запрос поступает в обработчик, прежде чем он достигнет конца (я предполагаю, что-то делать с максимальными запросами к обработчику?) это привело к тому, что некоторые сеансы остались открытыми в V $ SESSION, которые мне пришлось закрыть вручную.

Я наткнулся на этот бит кода:

OracleConnection.ClearAllPools();

И попытался запустить его, хотя обработчик оставлял сеансы открытыми, по крайней мере, они были бы закрыты этим кодом, в настоящее время он выполняется в конце блока using для OracleConnection (поэтому каждый раз, когда служба вызвал его, очищает пулы, надеется, что обработчику удастся выполнить это далеко!).

Так что использование метода ClearAllPools, похоже, работает, но я знаю, что это не идеальное решение.

1 голос
/ 24 января 2012

Попробуйте обернуть использование OracleConnection внутри блока использования (если вы используете C #):

using (OracleConnection conn = new OracleConnection(connectionString))
{
   ...
}

Это обеспечит правильную утилизацию после завершения использования.OracleConnection и OracleDataReader (в качестве другого примера) реализуют IDisposable, поэтому должны использоваться в операторе using.

1 голос
/ 20 января 2012

Обязательно оберните все соединения в блок try / finally. Недостаточно просто вызывать .Close () для каждого .Open (). Вы должны поместить вызов .Close () в блок finally. Самый простой способ сделать это - создать свои соединения с помощью блока using.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...