"열기 / 닫기"SqlConnection 또는 계속 열려 있습니까?


121

정적 메서드를 사용하여 간단한 정적 클래스에서 비즈니스 로직을 구현했습니다. 이러한 각 메소드는 호출시 SQL 연결을 열거 나 닫습니다.

public static void DoSomething(string something)
{
    using (SqlConnection connection = new SqlConnection("..."))
    {
        connection.Open();

        // ...

        connection.Close();
    }
}

하지만 연결을 열고 닫지 않으면 성능이 절약 된다고 생각 합니다 . OleDbConnection 클래스 (SqlConnection에 대해 확실하지 않음)로 오래 전에 몇 가지 테스트를 수행 했으며 다음과 같이 작동하는 데 확실히 도움이되었습니다 (내가 기억하는 한).

//pass the connection object into the method
public static void DoSomething(string something, SqlConnection connection)
{
    bool openConn = (connection.State == ConnectionState.Open);
    if (!openConn)
    {
        connection.Open();
    }

    // ....

    if (openConn) 
    {
        connection.Close();
    }
}

그래서 질문은-방법 (a) 또는 방법 (b)를 선택해야합니까? 연결 풀링이 저에게 성능을 저장했다는 또 다른 스택 오버플로 질문을 읽었습니다. 전혀 신경 쓸 필요가 없습니다.

추신. ASP.NET 앱입니다. 연결은 웹 요청 중에 만 존재합니다. 윈-앱이나 서비스가 아닙니다.


1
참고 DbConnection.StateChange사항 : DbConnection.State속성을 직접 확인하는 대신 이벤트를 사용 하여 연결 상태 변경의 변경 사항을 모니터링 하십시오 (로컬에 저장 될 수 있음) . 성능 비용을 절약 할 수 있습니다.
decyclone

1
누락 된 한 가지 세부 사항은이 메소드가 페이지 요청의 일부인 방법입니다. 호출되는 유일한 방법입니까 아니면 내 응답에서 가정했듯이 페이지 요청에서 호출되는 많은 방법 중 하나가 올바른 대답에 영향을 미칩니다.)
David Mårtensson dec

데이비드 -이 같은 방법의 제비는 :)라고되고있다
알렉스

1
사례 A는 Dispose에 대한 믿음이 부족함을 보여줍니다. stackoverflow.com/questions/1195829/… 및 MSDN의 예 msdn.microsoft.com/en-us/library/… 참조
user2864740

답변:


82

옵션 a를 고수하십시오 .

연결 풀링은 당신의 친구입니다.


37
IMHO-그는 가까이서도 안됩니다. 처분은 그것을 할 것입니다.
Royi Namir 2013 년

2
@RoyiNamir 나는 연결을 닫으라는 호출을 좋아합니다. 특히 코드베이스의 초보자와 초보자에게 적합합니다. 더 명확하고 읽기 쉽습니다.
edhedges

27
@edhedges "using"과 Close ()를 모두 사용하는 것은 궁극적으로 신규 이민자에게 혼란을 야기 할뿐입니다. 그들은 "사용"을 활용하는 목적을 이해하지 못할 것입니다. "닫기"를 사용하지 말고 "사용"의 목적을 가르치십시오. 그래서 그들은 더 잘 배우고 그들이 배운 것을 코드의 다른 부분에 적용 할 수 있습니다.
Luis Perez

1
"Open ()"을 호출해야합니까? 현재 다음과 같이 사용하고 있습니다. using (var conn = GetConnection ()) {} public SqlConnection GetConnection () {return new SqlConnection (_connectionString); }
ganders

79

매번 방법 (a)를 사용하십시오. 응용 프로그램 확장을 시작할 때 상태를 처리하는 논리는 그렇지 않으면 정말 고통 스러울 것입니다.

연결 풀링은 주석에 표시된대로 수행합니다. 애플리케이션이 확장 될 때 어떤 일이 발생하는지, 연결 열기 / 닫기 상태를 수동으로 관리하는 것이 얼마나 어려울 지 생각해보십시오. 연결 풀은이를 자동으로 처리하는 훌륭한 작업을 수행합니다. 성능이 걱정된다면 어떤 것도 차단되지 않도록 일종의 메모리 캐시 메커니즘을 생각해보십시오.


33

연결이 끝나면 항상 연결을 닫으십시오. 그러면 기본 데이터베이스 연결이 풀로 돌아가서 다른 호출자가 사용할 수 있습니다. 연결 풀링은 상당히 최적화되어 있으므로 그렇게해도 눈에 띄는 불이익이 없습니다. 조언은 기본적으로 트랜잭션과 동일합니다. 완료되면 짧고 가깝게 유지하십시오.

다중 연결을 사용하는 코드 주위에 단일 트랜잭션을 사용하여 MSDTC 문제가 발생하면 실제로 연결 개체를 공유하고 트랜잭션이 완료된 후에 만 ​​닫아야합니다.

그러나 여기서는 작업을 직접 수행하고 있으므로 DataSets, Linq to SQL, Entity Framework 또는 NHibernate와 같이 연결을 관리하는 도구를 조사 할 수 있습니다.


일반적으로 모든 메서드 호출 내에서 연결을 열고 닫는 것이 아니라 각 페이지 요청에 대해 한 번 씩만 연결하면됩니다. 그게 내가 적어도 배운 것입니다;) 열기와 닫기는 시간이 걸립니다.
David Mårtensson

8
@David Martensson-SqlConnection.Open을 호출 할 때 연결이 실제로 열리고 닫히지 않습니다. ASP.NET은 연결 문자열이 이전에 사용 된 연결 문자열과 일치 할 때 풀에서 활성 연결을 재활용합니다. 이와 관련된 오버 헤드는 중요하지 않으며 추가로 "스스로 수행"하려는 경우 이후 사용 시마다 연결이 여전히 활성 상태인지 확인하는 모든 관리 작업을 가정해야하므로 복잡성과 오버 헤드가 추가됩니다. 연결 풀링을 사용하는 경우 가장 좋은 방법은 모든 사용에 대해 열고 닫는 것입니다.
Jamie Treworgy 2010

2
내 모든 존경심으로, "항상 긴밀한 관계"라는 대답은 질문에 잘 맞지 않습니다 ... 나는 그들을 닫습니다. 문제는-언제입니다.
Alex

@David Martensson "한 페이지 당 한 번"은 지나치게 단순화되었습니다. 차례대로 실행할 데이터베이스 명령이 여러 개있는 경우 실행하는 동안 연결을 열어 둘 수 있습니다. 닫았다가 다시 열면 약간의 오버 헤드가 발생합니다. 연결이 풀로 이동하여 잠시 후에 검색됩니다.
Concrete Gannet

1
@David Martensson 그러나 유휴 연결을 유지하지 마십시오. 사용자의 작업 또는 다른 작업을 기다리고있는 경우 닫습니다. 확실하지 않은 경우 닫으십시오. 다른 사람이 연결을 완료하고 풀링하기를 바라며 가능한 한 늦게 엽니 다. 그런 다음 호의를 보답합니다-합리적으로 가능한 한 빨리 닫습니다.
Concrete Gannet

13

면책 조항 : 이것이 오래되었다는 것을 알고 있지만이 사실을 쉽게 입증 할 수있는 방법을 찾았으므로 2 센트 가치를 투자하고 있습니다.

풀링이 실제로 더 빨라질 것이라고 생각하는 데 문제가있는 경우 다음을 시도해보십시오.

어딘가에 다음을 추가하십시오.

using System.Diagnostics;
public static class TestExtensions
{
    public static void TimedOpen(this SqlConnection conn)
    {
        Stopwatch sw = Stopwatch.StartNew();
        conn.Open();
        Console.WriteLine(sw.Elapsed);
    }
}

이제 모든 호출을 Open()로 바꾸고 TimedOpen()프로그램을 실행하십시오. 이제 각각의 고유 한 연결 문자열에 대해 콘솔 (출력) 창에 하나의 장기 실행 창이 열리고 매우 빠르게 열리게됩니다.

레이블 new StackTrace(true).GetFrame(1) +을 지정하려면에 대한 호출에 추가 할 수 있습니다 WriteLine.


9

물리적 연결과 논리적 연결에는 차이가 있습니다. DbConnection은 일종의 논리적 연결이며 Oracle에 대한 기본 물리적 연결을 사용합니다. DbConnection을 닫거나 여는 것은 성능에 영향을주지 않지만 코드를 깨끗하고 안정적으로 만듭니다.이 경우 연결 누수가 불가능합니다.

또한 db 서버에서 병렬 연결에 대한 제한이있는 경우에 대해 기억해야합니다. 연결을 매우 짧게 만들어야한다는 점을 감안하면됩니다.

연결 풀을 사용하면 연결 상태를 확인하지 않아도됩니다. 연결 풀을 열고 사용하고 즉시 닫으면됩니다.


예, 연결이 연결이 아닙니다. 즉, DbConnection이 물리적 연결이 아닙니다. DbConnection은 기본 물리적 연결을 조작하는 메서드와 속성을 제공하는 .NET 클래스입니다.
Concrete Gannet

불행히도 이것이 모두 암묵적으로 수행되었다는 것이 즉시 분명하지는 않았지만 문서는 그것에 대해 자세히 설명합니다. docs.microsoft.com/en-us/dotnet/framework/data/adonet/…
Austin Salgat

2

일반적으로 각 트랜잭션에 대해 하나의 연결을 유지해야합니다 (병렬 계산 없음).

예를 들어 사용자가 청구 작업을 실행할 때 애플리케이션은 먼저 사용자의 잔액을 찾아 업데이트해야하며 동일한 연결을 사용해야합니다.

ado.net에 연결 풀이 있어도 디스패치 연결 비용은 매우 낮지 만 연결 재사용이 더 나은 선택입니다.

애플리케이션에서 하나의 연결 만 유지하지 않는 이유

일부 쿼리 또는 명령을 실행할 때 연결이 차단되기 때문에 응용 프로그램이 동시에 하나의 db 작업 만 수행하므로 성능이 얼마나 저하됩니다.

한 가지 더 문제는 사용자가 열려 있지만 작업이 없어도 응용 프로그램이 항상 연결된다는 것입니다. 많은 사용자가 응용 프로그램을 열면 db 서버는 곧 모든 연결 소스의 비용을 지불하지만 사용자는 연결하지 않습니다. 아무것도.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.