Dispose () SqlConnections를 사용하지 않는 것이 얼마나 나쁜가요?


14

개인적으로, 나는 문을 사용하여 IDisposable을 구현하는 ADO 객체를 넣지 않으면 두드러기로 나뉩니다. 그러나 현재 계약에서, 자체 개발 한 엔터프라이즈 프레임 워크 "데이터 액세스 공급자"코드는 1) IDisposable을 구현하지 않으며 2) 언제 어디서나 사용하는 모든 것에 대해 Dispose ()를 호출하지 않습니다. 사용자는 데이터 액세스를 위해이 프레임 워크를 많이 사용하는 Winforms 애플리케이션의 성능 문제에 대해 많은 불만을 제기하고 있으며, 성능에 영향을 줄 수있는 코드에는 다른 많은 문제가 있지만,이 비명은 단지 비명을 지르고 있습니다. 다른 것보다 낮은 매달린 과일.

따라서 "이유는 폐기하고 사용하십시오"와 같은 말을 넘어서서,이 사람들에게 이것이 정말로, 정말로 나쁘다는 것을 납득시키기 위해 무엇을 말할 수 있습니까?


5
Heh .. 나의 추측은, 어느 시점에서 설득력이 필요하지 않을 것입니다 :)
dr Hannibal Lecter

답변:


6

나는 당신이 할 수있는 최선의 방법은 Dispose() 여기 에 관한 Microsoft의 패턴 및 관행을 지적하는 것 입니다. 바로 앞에있는이 도구를 사용하지 않으면 전체 결과를 볼 수 있습니다.


1
상단에서 "이것은 폐기 된 콘텐츠입니다"라고 소리 지르지 않는 버전을 찾을 수 있으면 좋겠습니다.
AJ Johnson

아시다시피, 내 눈은 그 위에 빛이났습니다. 그러나 이제는이 책을주의 깊게 읽으면서 사람들이 해당 페이지에서 폐기 된 "아직 사용중인"기술이 무엇인지 궁금합니다. 아마도 CAS?
Jesse C. Slicer

더 자세히 살펴보면 여전히 대부분 나와 관련이 있습니다. 왜 은퇴로 표시되었는지 확실하지 않습니다.
AJ Johnson

10

SQL 연결에서 Dispose 메서드를 호출하지 않으면 사용을 마치면 해당 연결이 연결 풀로 다시 반환되지 않습니다.

성능 문제가있는 경우 데이터베이스에서 최대 연결이 열려 있다고 생각합니다. DBA가이를 쉽게 확인할 수 있습니다.

Microsoft의 모범 사례에서는 Using 문 내에 연결 코드를 배치하여 연결이 삭제되고 연결이 풀로 다시 반환되도록합니다.


Close연결 풀로 다시 해제하기에 충분한 호출 입니다. 이 질문에는 명시 적으로 사용 Close되지 않은 내용이 나와 있지 않습니다 .
user2864740

9

데이터베이스 연결 풀의 크기는 제한되어 있으며 채워지면 새 연결은 기존 연결이 해제 될 때까지 기다립니다. 작업을 마치 자마자 처리하지 않으면 결국 파이널 라이저가 실행될 때 릴리스되지만 나중에는 결정되지 않은 시간입니다. 새 연결을 열 때 오랜 지연이 발생합니다.

최악의 경우 연결 풀을 비활성화했을 수 있습니다. 아마도 그들은 잠시 후 앱이 "연결 대기 시간 초과"오류를 반환하고 연결 풀을 비활성화하면 해당 문제가 "해결"되었음을 발견했습니다. 그러나 이것은 매번 완전히 새로운 연결을 생성한다는 것을 의미하기 때문에 훨씬 더 나쁩니다 . 놀랍게도 리소스 집약적입니다. 데이터베이스에 수백 개의 연결이 열려 있으면 성능 문제가 발생하는 것은 당연합니다.

이러한 모든 문제를 해결하는 올바른 방법은 연결을 마치는 즉시 연결을 해제하는 것입니다. 가장 좋은 아이디어는 필요한만큼 정확하게 연결을 열어두고 더 이상 유지하지 않는 것입니다.


1
이것보다 조금 더 나쁩니다. 풀이 충분히 백업되면 관리 도구에서의 연결 시도를 포함하여 많은 연결 시도가 실패하고 데이터베이스를 효과적으로 잠글 수 있습니다.
Joel Coehoorn '

3

어떤 심각한 응용 프로그램에서 나는 그것이 꽤 나쁘다고 말합니다. 이러한 개체를 강제 종료하면 성능이 저하 될뿐만 아니라 비전문가이기도합니다. 좋은 소식은 Microsoft가 객체 계층 구조에서 Finalize를 구현한다는 것입니다.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

가지고 System.Data.SqlClient.SqlConnection예를 들면 :

System.ComponentModel.Component <-Finalize 처리 패턴을 구현합니다.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

객체는 결국 폐기되지만 결정적이지 않은 특성으로 인해 성능이 저하됩니다.


0

글쎄, 당신은 연결을 종료하지 않습니다. 따라서 a) 자동으로 삭제하거나 b) 클라이언트가 사용하지 않아도 순환 및 업데이트를 수행해야합니다.

b) 당신이 묘사 한 성능 적중으로 인해 가정 합니다. 그러나 이것이 유일한 이유는 아닙니다.

클라이언트 쪽에서 연결을 닫아야하지만 서버 쪽에서도 페일 세이프를 구현해야합니다. 그렇지 않으면 데이터베이스 서버가 god-knows-when에 릴리스 될 때까지 처리해야한다는 추가 쓰레기가 쌓여 있습니다.

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