일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Stock
- 주식
- MYSQL
- 7월 공모주 청약 일정
- Eclipse
- 6월 공모주 청약 일정
- php
- JavaScript
- SQL
- Stock ipo
- java
- Oracle
- jquery
- 자바
- html
- codeigniter
- 주식 청약
- 맥
- 주식 청약 일정
- 자바스크립트
- IPO
- 리눅스
- css
- 공모주 청약 일정
- 코드이그나이터
- 오라클
- 제이쿼리
- 공모주
- linux
- 공모주 청약
- Today
- Total
개발자의 끄적끄적
[cubrid] PHP를 이용하여 CUBRID 사용할 때의 주의점 [펌] 본문
[cubrid] PHP를 이용하여 CUBRID 사용할 때의 주의점 [펌]
CUBRID DBMS 를 사용하여 PHP 응용을 개발할 때의 MySQL 과의 차이점 때문에 발생할 수 있는 문제에 대해 요약 정리하고자 한다.
1. Select 절이라도 꼭 트랜잭션 처리를 해주자 . ( Commit/Rollback 을 해주자 ).
대부분의 MySQL 개발자의 경우 Select 절을 수행후 Transaction 처리를 않하는 것을 습관적으로 사용하고 있다.
그러나 CUBRID는 이의 경우에라도 꼭 처리를 해주어야 한다. ( 이는 트랜잭션에 처리에 관한 정석을 따른다고 할까? )
CUBRID 도 특별히 문제가 발생하는 것은 아닌데, 문제는 어떤 테이블에 대해 전체 삭제 등을 처리 할 경우에 문제가 발생한다.
이는 CUBRID의 PHP API 가 사용하는 CCI 라는 Interface 를 사용하게 되는데, 아직 CCI 는 autocommit 을 지원하지 않기 때문에 발생한다.
JDBC 인터페이스는 autocommit 을 지원하기 때문에 autocommit 모드 하에서는 아래와 같은 문제가 발생하지 않는다.
최근에 맡고 있는 어떤 서비스에서 Query 들이 테이블 Lock 을 기다리면서 서비스가 먹통이 되는 현상이 발견되었다.
이것의 문제는 Insert/Update/Delete 등의 경우에는 트랜잭션 처리를 해주어서 별 문제가 되지 않는데, 새벽시간을 통해 매일 그 날의 통계정보를 갱
신하는 테이블에 대한 작업 때문에 발생하였다. 작업은 통계 테이블을 모두 삭제하고, 갱신된 통계정보를 입력하는 질의였다. 아래의 문제로 인해 서비
스 장애가 발생하였으나 아래의 내용을 잘 보면 피해 갈수 있는 방법이 있다.
간단히 재현하면 아래와 같다.
트랜잭션 T1, T2, T3 가 있다고 가정한다. 재현테이블은 foo 라고 하자.
T1 : select ... from foo , 또는 foo 를 포함하는 조인 질의 수행,
T2 : delete from foo 실행 , 조건없는 delete 테이블 작업.
T3 : select ... from foo 를 수행.
T1 : autocommit 을 끈 상태에서 select 질의를 수행한다.
csql> ;au off === <Result of SELECT Command in Line 2> === a b
1 command(s) successfully processed. |
이 경우의 lockdb 를 살펴보면. foo 테이블에 대해 IS_LOCK 이 잡힌다. 질의 가 수행되고 commit/Rollback 이 수행되면 IS_LOCK 은 놓게된다.
OID = 0| 551| 2 Object type: Class = foo. Total mode of holders = IS_LOCK, Total mode of waiters = NULL_ LOCK. Num holders= 1, Num blocked-holders= 0, Num waiters= 0 LOCK HOLDERS: Tran_index = 1, Granted_mode = IS_LOCK, Count = 3, Nsub granules = 0 |
테이블에 IS_LOCK 이 잡힌 상태에서 해당 테이블을 모두 삭제해본다.
이경우가 T2이다.
T1이 끝나기 전에 T2 가 수행되면 T2 는 테이블 전체 삭제이므로 IX_LOCK 단계에서 X_LOCK 을 잡기 위해 T1이 IS_LOCK 을 놓기 위해 기다린다.
이 때의 LockDB 정보는 아래와 같다. T2 는 Lock Timeout 이 300 으로 설정되어 300초 동안 기다리다가 aboart 된다.
OID = 0| 551| 2 Object type: Class = foo. Total mode of holders = X_LOCK, Total mode of waiters = NULL_LOCK. Num holders= 1, Num blocked-holders= 1, Num waiters= 0 LOCK HOLDERS: Tran_index = 1, Granted_mode = IS_LOCK, Count = 2, Nsubgranules = 0 BLOCKED LOCK HOLDERS: Tran_index = 2, Granted_mode = IX_LOCK, Count = 2, Nsubgranules = 0 Blocked_mode = X_LOCK Start_waiting_at = Tue Dec 1 16:54:04 2009 Wait_for_nsecs = 300000 |
T1 이 IS_LOCK 을 놓기 전에는 T2 가 실행이 되질 않는다.
여기에 해당 테이블에 Select 질의를 수행하는 T3 가 실행된다.
이 경우에 T3 는 또한 T2 가 끝나기를 기다린다.
OID = 0| 551| 2 Object type: Class = foo. Total mode of holders = X_LOCK, Total mode of waiters = IS_LOCK. Num holders= 1, Num blocked-holders= 1, Num waiters= 1 LOCK HOLDERS: Tran_index = 1, Granted_mode = IS_LOCK, Count = 2, Nsubgranules = 0 BLOCKED LOCK HOLDERS: Tran_index = 2, Granted_mode = IX_LOCK, Count = 2, Nsubgranules = 0 Blocked_mode = X_LOCK Start_waiting_at = Tue Dec 1 16:54:04 2009 Wait_for_nsecs = 300000 LOCK WAITERS: Tran_index = 3, Blocked_mode = IS_LOCK Start_waiting_at = Tue Dec 1 16:57:50 2009 Wait_for_nsecs = 300000 |
이 상황이 되면 T2 가 끝나기 전에 T3, 그 뒤에 오는 Select 질의 들이 모두 T2 가 끝나기를 기다리게 되는데, 이럴 경우에 T2 가 끝나기전에는 마냥 기다리게 된다. LockTimeout 이 300 초가 흐른 뒤에 보면 아래와 같은 오류가 찍히고, T3 는 수행이 된다. 이럴 경우에는 적어도 300초가 흐르면 수행은 되지만 만약 LockTimeout 이 -1 이면 DB는 먹통이 되는 것 처럼 보이게 된다.
csql> delete from foo In the command from line 1, ERROR: Your transaction (index 2, dba@cdbs014.cub|23041) timed out waiting on X_LOCK lock on class foo. You are waiting for user(s) dba@cdbs014.cub|22983, dba@cdbs014.cub|23069 to finish. |
이를 해결할 수 있는 방법은 1차적으로는 모든 select 질의에 대해서도 Commit/Rollback 을 명시해 주는 것이다. 현재 CUBRID의 PHP API 의 autocommit 이 지원될 때 까지는 , 2차 방법으로는 T2 에 대해 테이블 Lock 을 잡지 않도록 하는 것이다. 이럴 경우에는 T3 , T4 계속 들어오는 트랜잭션이 잘못된 것을 볼 수 있을 수도 있는데, 서비스가 멈추는 현상은 발생하지 않을 것이다.
Index scan 을 하면서 삭제를 한다면 테이블락을 잡지 않고 인스턴스( 튜플 ) 락을 잡기 때문에 뒤에오는 Select 질의에는 영향이 없다.
따라서 MySQL 로 PHP를 개발하던 개발자들이 CUBRID 를 사용함에 있어서 유의 할 점 하나는 Select 절이어도 꼭 Commit/Rollback 을 처리해 줘야 한다.
위와 같은 현상이 발생하지 않도록 어떤 DBMS 를 사용할 때에도 꼭 트랜잭션 처리는 중요하다.
※ Lock 관련 메뉴얼 ( http://www.cubrid.com/online_manual/cubrid_820/syntax/syntax_tran_lock_intro.htm ) 를 참조 바랍니다.
2. select 질의 수행해주고 request handle 을 꼭 닫자.
select 질의를 수행하면 CUBRID 의 client 를 처리하는 cub_cas 라는 프로세스가 요청한 질의에 대한 Parsing 을 수행하여 Prepare statement 및 결과 ResultSet 등을 메모리에 담고 있다.
select 질의를 cubrid_execute 를 실행한 후 해당 request handle 을 close 를 해주지 않으면 cub_cas 의 메모리가 급격히 증가하게 되고, 해당 connection 이 여러개의 cub_cas 에 연결되어있을 경우 서버의 리소스를 점유하여 성능 저하 현상이 발생한다.
따라서 select 질의 수행후 해당 request handle 에 대해 fetch 가 끝나면 아래 예제와 같이 꼭 close 를 해주어야 한다.
$con = cubrid_connect ("dbsvr.cubrid.com", 12345, "demodb"); if ($con) { echo "connected successfully"; $req = cubrid_execute ( $con, "select * from members", CUBRID_INCLUDE_OID | CUBRID_ASYNC); if ($req) { while ( list ($id, $name) = cubrid_fetch ($req) ){ echo $id; echo $name; } cubrid_close_request($req); } cubrid_disconnect($con); } |
출처 : https://m.blog.naver.com/PostView.nhn?blogId=windyhan&logNo=110075051208
'개발 > sql' 카테고리의 다른 글
[cubrid] pk 수 증가 방법 [펌] (0) | 2020.05.11 |
---|---|
[cubrid] alter column 방법 (0) | 2020.05.11 |
[cubrid] 테이블 복사하기 (0) | 2020.05.07 |
[cubrid] 큐브리드 매니저 호스트 접속 시 JDBC 드라이버 찾을 수 없는 오류 해결 [펌] (0) | 2020.05.06 |
[cubrid] 큐브리드 버전 확인 (0) | 2020.05.06 |