2008년 12월 19일 금요일

ADO(MySQL ODBC) 에서의 CursorLocation=3 관련 메모리 문제

Asp(Vbscript) 는 해본적이 너무 오래되서, 잊고 있었던 내용 입니다. (요즘엔 닷넷만 해서.....) ADO 에서의 커서를 생성하는 위치를 지정하는 CursorLocation 에 관련되어 메모리 문제 입니다.

CursorLocation 은 ADO 에서, 레코드셋을 만들기 위해서 커서의 생성 위치를 어디에 두느냐? 라는 것을 지정해 줄수 있는 옵션 입니다. 물론 지정하지 않으면 기본값이 Server 측인데,. 즉 DB 서버 라는 얘기 입니다.

CursorLocationEnum
http://msdn.microsoft.com/en-us/library/ms677542(VS.85).aspx

문제는. CursorLocation=3 으로 클라이언트 측에 둘때의 문제 입니다.

물론 클라이언측에 두었을 때의 잇점이 많이 있기 때문에 사용하는 것도 있지만,. 쿼리문에서 사용되는 테이블의 레코드 갯수가 적을 때에는 문제를 느끼기 어렵고, 대량의 레코드를 갖고 있는 경우에 문제가 됩니다.

특히,. 집계 함수를 사용하는 경우인데, 이때 커서 위치가 클라이언측에 있는 경우, 이를 테면 웹서버에 두는 경우 웹프로세스(작업자프로세스)에 메모리 점유가 상당하는 점 입니다. (운영하는 서버에서는 단 5분 만에 500M 를 초과 하며, 해당 테이블의 레코드 갯수가 20만개가 넘습니다.)

이러한 비정상적인 메모리 점유에 대한 내용을 확인하던 중에, 꾀 흥미로운 점을 발견 했습니다. 즉 ODBC 드라이버에서 MySQL 에 던지는 쿼리 형태 입니다.

081218  4:41:12   46781 Connect     wssplex@xxx.xxx.xxxx.xxx on wssplex
          46781 Query       SET SQL_AUTO_IS_NULL = 0
          46781 Query       select database()
          46781 Query       select database()
          46781 Query       SELECT @@tx_isolation
          46781 Query       select count(distinct(컬럼)) c from 테이블 where 컬럼 = '값'
081218  4:41:13   46781 Query       SELECT * FROM 테이블
081218  4:41:34   46781 Query       select database()

위에 보이는 것처럼, select * 를 하여 테이블을 통째로 쿼리 한다는 점입니다. 이 통째 쿼리한 결과는 웹서버측에 반환되고, 이것을 받은 웹프로세스는 메모리가 급격하게 증가 합니다.

잠시 동안은 이러한 쿼리가 DB 측에 날라 간다는 점을 알지 못하였고,. 위 쿼리를 사용한 웹페이지를 아무리 확인해 봐도 메모리 점유를 할만한 부분이 있지 않았습니다.

물론,. 위의 이러한 점을 확인하기 위해서 정확하게 웹서버측에서 전달되는 것을 확인하기 위해서 패킷 캡쳐를 하여 문자열을 확인해 보기도 하였습니다.

..C..B..#.$h..E..\..@...-....L...J....A.....-.P..j.k..0....
select count(distinct(컬럼)) c from 테이블 where 컬럼 = '값'
IP (tos 0x0, ttl 128, id 54945, offset 0, flags [DF], proto 6, length: 65) xxx.xxx.xxx.xxx.4299 > xxx.xxx.xxx.xxx.3306: P [tcp sum ok] 3716:3741(25) ack 2161 win 65061
..C..B..#.$h..E..A..@...-....L...J....A..%...*P..%.........
SELECT * FROM 테이블

이런식의 쿼리가 되는 것은,. CursorLocation 을 클라이언트 측에 두었기 때문 입니다.

그러나 MSSQL 의 경우에도 이런식의 쿼리 형태 인지는 확인해 보지 않았습니다. 만약 MySQL 에서만 그랬다면 MySQL 의 특성이거나 MyODBC 드라이버 문제이지 않을까도 생각해 봅니다. 모든 DB에서의 동일한 현상이라면 ADO 의 작동 방식일수도 있겠고... (*혹시 아시는 분은 댓글 부탁드려요.^^)

CursorTypes, LockTypes, and CursorLocations
http://dev.mysql.com/tech-resources/articles/vb-cursors-and-locks.html

물론, 커서 위치를 단순하게 서버측이냐, 클라이언트냐 의 문제 보다는 데이터를 어떻게 이용하는 방법에 따라서 불가피하게 특정 커서 위치를 선택해야 하는 경우도 있을것 입니다.

댓글 없음:

댓글 쓰기

HttpClient 에서 비동기 호출시 System.Threading.Tasks.Task 오류

client.PostAsync().Result; 하나 이상의 오류가 발생했습니다., 위치: System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) 이 요청을...