:meta-keywords: cubrid transaction, database transaction, cubrid locking, database locking, cubrid concurrency, multiversion concurrency control, mvcc, isolation level, database recovery :meta-description: This chapter covers issues relating to concurrency (MVCC) and restore, as well as how to commit or rollback transactions in CUBRID database. .. _database-transaction: ë°ì´í„°ë² ì´ìФ 트랜ìžì…˜ ===================== ë°ì´í„°ë² ì´ìФ 트랜ìžì…˜ì€ CUBRID 질ì˜ë¬¸ì„ ì¼ê´€ì„±(다중 ì‚¬ìš©ìž í™˜ê²½ì—서 ìœ íš¨í•œ 결과를 만들어내는 것)ê³¼ 복구(시스템 실패와 ê°™ì€ ì–´ë–¤ ìž¥ì• ì—ë„ ì»¤ë°‹ëœ íŠ¸ëžœìžì…˜ì˜ 결과를 ìœ ì§€í•˜ëŠ” 것과, ì–´ë–¤ ê³ ìž¥ì—ë„ ë¶ˆêµ¬í•˜ê³ ì¤‘ë‹¨ëœ íŠ¸ëžœìžì…˜ì€ ë°ì´í„°ë² ì´ìŠ¤ë¡œë¶€í„° 무효화ë˜ëŠ” ê²ƒì„ ë³´ìž¥í•˜ëŠ” 것)ì˜ ë‹¨ìœ„ë¡œ 그룹화한다. í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ì€ ë°ì´í„°ë² ì´ìŠ¤ì— ì ‘ê·¼í•˜ê³ ê°±ì‹ í•˜ëŠ” í•˜ë‚˜ì˜ ì§ˆì˜ë¬¸ ë˜ëŠ” 여러 질ì˜ë¬¸ìœ¼ë¡œ 구성ëœë‹¤. CUBRID는 ë§Žì€ ì‚¬ìš©ìžê°€ ë™ì‹œì— ë°ì´í„°ë² ì´ìŠ¤ì— ì ‘ê·¼í•˜ë„ë¡ í•˜ê³ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¶ˆì¼ì¹˜ë¥¼ 방지하기 위하여 ì‚¬ìš©ìž ê°„ ì ‘ê·¼ê³¼ ê°±ì‹ ì„ ê´€ë¦¬í•œë‹¤. 예를 들어 ë°ì´í„°ê°€ 한 사용ìžì— ì˜í•´ ê°±ì‹ ë˜ì—ˆì„ 때 ê·¸ 트랜ìžì…˜ì— ê´€ë ¨ëœ ë°ì´í„°ì˜ 변화는 ê°±ì‹ ì´ ì»¤ë°‹ë 때까지 다른 사용ìžë‚˜ ë°ì´í„°ë² ì´ìФì—서 ì¼ì–´ë‚˜ëŠ” 다른 트랜ìžì…˜ì— ë³´ì´ì§€ 않는다. 트랜ìžì…˜ì´ 커밋ë˜ì§€ ì•Šê³ ë¡¤ë°±ë 수 있기 ë•Œë¬¸ì— ì´ ì›ì¹™ì€ 중요하다. 트랜ìžì…˜ 처리 결과를 í™•ì‹ í• ë•Œê¹Œì§€, ë°ì´í„°ë² ì´ìŠ¤ì— ì˜êµ¬ì 으로 ê°±ì‹ í•˜ëŠ” ê²ƒì„ ì—°ê¸°í• ìˆ˜ 있다. ë˜í•œ 트랜ìžì…˜ 처리 ê³¼ì •ì—서 ì‘ìš© 프로그램ì´ë‚˜ 컴퓨터 시스템ì—서 ë§Œì¡±í• ìˆ˜ 없는 결과나 실패가 ë°œìƒí•˜ë©´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ëª¨ë“ ê°±ì‹ ì„ ì œê±°(**ROLLBACK**)í• ìˆ˜ 있다. 트랜ìžì…˜ì˜ ëì€ **COMMIT WORK** ë˜ëŠ” **ROLLBACK WORK** 문으로 ê²°ì •ëœë‹¤. **COMMIT WORK** ë¬¸ì€ ë°ì´í„°ë² ì´ìŠ¤ì˜ ëª¨ë“ ê°±ì‹ ì„ ì˜êµ¬ì 으로 만드는 ë°˜ë©´ì— **ROLLBACK WORK** ë¬¸ì€ íŠ¸ëžœìžì…˜ì—서 ìž…ë ¥ëœ ëª¨ë“ ê°±ì‹ ì„ ë¬´íš¨í™”ì‹œí‚¨ë‹¤. 트랜ìžì…˜ 커밋 ------------- ë°ì´í„°ë² ì´ìФì—서 ì¼ì–´ë‚œ ê°±ì‹ ë“¤ì€ **COMMIT WORK** ë¬¸ì´ ì£¼ì–´ì§€ê¸° ì „ê¹Œì§€ ì˜êµ¬ížˆ ì €ìž¥ë˜ì§€ 않는다. "ì˜êµ¬ížˆ(permanently)" ì €ìž¥ëœë‹¤ëŠ” ê²ƒì€ ë””ìŠ¤í¬ì— ì €ìž¥ì´ ì™„ë£Œë˜ëŠ” ê²ƒì„ ì˜ë¯¸í•œë‹¤. 키워드 **WORK** 는 ìƒëžµì´ 가능하다. 추가로 ë°ì´í„°ë² ì´ìŠ¤ì˜ ë‹¤ë¥¸ 사용ìžëŠ” ë³€ê²½ì´ ì˜êµ¬ížˆ ë°˜ì˜ë˜ê¸° ì „ê¹Œì§€ëŠ” 변경 사í•ì„ ë³¼ 수 없다. 예를 들어 í…Œì´ë¸”ì— ìƒˆë¡œìš´ í–‰ì„ ì‚½ìž…í–ˆì„ ë•Œ ë°ì´í„°ë² ì´ìФ 트랜ìžì…˜ì´ 커밋ë˜ê¸° ì „ê¹Œì§€ ê·¸ í–‰ì— ì ‘ê·¼í• ìˆ˜ 있는 ê²ƒì€ ê·¸ í–‰ì„ ì‚½ìž…í•œ 사용ìžë¿ì´ë‹¤(**UNCOMMITTED INSTANCES** 격리 ìˆ˜ì¤€ì„ ì‚¬ìš©í•˜ë©´ 다른 사용ìžê°€ ì¼ê´€ì„±ì´ 없는 커밋ë˜ì§€ ì•Šì€ ê°±ì‹ ì„ ë³¼ ìˆ˜ë„ ìžˆë‹¤). 트랜ìžì…˜ì´ ì»¤ë°‹ëœ í›„ì—는 트랜ìžì…˜ì—서 íšë“한 ëª¨ë“ ìž ê¸ˆì´ í•´ì œëœë‹¤. :: COMMIT [WORK]; .. code-block:: sql -- ;autocommit off -- AUTOCOMMIT IS OFF SELECT name, seats FROM stadium WHERE code IN (30138, 30139, 30140); :: name seats ============================================= 'Athens Olympic Tennis Centre' 3200 'Goudi Olympic Hall' 5000 'Vouliagmeni Olympic Centre' 3400 ë‹¤ìŒ **UPDATE** ë¬¸ì€ 3ê°œì˜ stadiumì˜ seats 칼럼 ê°’ì„ ë³€ê²½í•œë‹¤. 결과를 ê²€í† í•˜ê¸° 위해 ê°±ì‹ ì´ ì¼ì–´ë‚˜ê¸° ì „ì— í˜„ìž¬ì˜ ê°’ê³¼ ì´ë¦„ì„ ê²€ìƒ‰í•œë‹¤. 기본ì 으로 csqlì€ ìžë™ìœ¼ë¡œ autocommit으로 ìž‘ë™ë˜ë¯€ë¡œ, ì˜ˆì œì—서는 autocommit 모드를 off로 ì„¤ì •í•œ 후 ë™ìž‘ì„ ì‹œí—˜í•œë‹¤. .. code-block:: sql UPDATE stadium SET seats = seats + 1000 WHERE code IN (30138, 30139, 30140); SELECT name, seats FROM stadium WHERE code in (30138, 30139, 30140); :: name seats ============================================ 'Athens Olympic Tennis Centre' 4200 'Goudi Olympic Hall' 6000 'Vouliagmeni Olympic Centre' 4400 만약 ê°±ì‹ ì´ ì œëŒ€ë¡œ ì´ë£¨ì–´ 졌다면 ë³€ê²½ì„ ì˜êµ¬ì 으로 만들 수 있다. ì´ë•Œ 아래처럼 **COMMIT WORK** ë¬¸ì„ ì‚¬ìš©í•œë‹¤. .. code-block:: sql COMMIT [WORK]; .. note:: CUBRIDì—서는 트랜ìžì…˜ 처리 시 기본ì 으로 ìžë™ 커밋 모드로 ì§€ì •ëœë‹¤. ìžë™ 커밋 모드는 ëª¨ë“ SQL ë¬¸ì„ ìžë™ìœ¼ë¡œ 커밋 ë˜ëŠ” 롤백하는 모드로서, 해당 SQL ë¬¸ì´ ì •ìƒ ìˆ˜í–‰ë˜ë©´ 해당 트랜ìžì…˜ì„ ìžë™ ì»¤ë°‹í•˜ê³ , 오류가 ë°œìƒí•˜ë©´ 트랜ìžì…˜ì„ 롤백한다. ì´ëŸ¬í•œ ìžë™ 커밋 모드는 ëª¨ë“ ì¸í„°íŽ˜ì´ìФì—서 ì§€ì›ë˜ë©°, CCI, PHP, ODBC, OLE DB ì¸í„°íŽ˜ì´ìŠ¤ëŠ” 브로커 파ë¼ë¯¸í„°ì¸ **CCI_DEFAULT_AUTOCOMMIT** ì„ í†µí•´ ì‘ìš© 프로그램 시작 ì‹œì˜ ìžë™ 커밋 모드를 ì„¤ì •í• ìˆ˜ 있다. 브로커 파ë¼ë¯¸í„° ì„¤ì •ì´ ìƒëžµë 경우 ê¸°ë³¸ê°’ì€ **ON** ì´ë‹¤. CCI ì¸í„°íŽ˜ì´ìŠ¤ëŠ” **cci_set_autocommit** (), PHP ì¸í„°íŽ˜ì´ìŠ¤ëŠ” **cubrid_set_autocommit** () 함수를 ì´ìš©í•˜ì—¬ ì‘ìš© 프로그램 ë‚´ì—서 ìžë™ 커밋 모드 ì„¤ì • 여부를 ë³€ê²½í• ìˆ˜ 있다. CSQL ì¸í„°í”„리터ì—서 ìžë™ 커밋 모드를 ì„¤ì •í•˜ëŠ” 세션 ëª…ë ¹ì–´(**;AUtocommit**)ì— ëŒ€í•´ì„œëŠ” :ref:`csql-session-commands` 를 참조한다. 트랜ìžì…˜ 롤백 ------------- **ROLLBACK WORK** ë¬¸ì€ ë§ˆì§€ë§‰ 트랜ìžì…˜ ì´í›„ì˜ ëª¨ë“ ë°ì´í„°ë² ì´ìŠ¤ì˜ ê°±ì‹ ì„ ì œê±°í•œë‹¤. **WORK** 키워드는 ìƒëžµ 가능하다. ì´ê²ƒì€ ë°ì´í„°ë² ì´ìŠ¤ì— ì˜êµ¬ì 으로 ìž…ë ¥í•˜ê¸° ì „ì— ë¶€ì •í™•í•˜ê³ ë¶ˆí•„ìš”í•œ ê°±ì‹ ì„ ë¬´íš¨í™”í• ìˆ˜ 있다. 트랜ìžì…˜ ë™ì•ˆ íšë“한 ëª¨ë“ ìž ê¸ˆì€ í•´ì œëœë‹¤. :: ROLLBACK [WORK]; ë‹¤ìŒ ì˜ˆì œëŠ” ë™ì¼í•œ í…Œì´ë¸”ì˜ ì •ì˜ì™€ í–‰ì„ ìˆ˜ì •í•˜ëŠ” ë‘ ê°œì˜ ëª…ë ¹ì„ ë³´ì—¬ì£¼ê³ ìžˆë‹¤. .. code-block:: sql -- csql> ;autocommit off CREATE TABLE code2 ( s_name CHAR(1), f_name VARCHAR(10) ); COMMIT; ALTER TABLE code2 DROP s_name; INSERT INTO code2 (s_name, f_name) VALUES ('D','Diamond'); :: ERROR: s_name is not defined. *code* í…Œì´ë¸”ì˜ ì •ì˜ì—서 *s_name* ì¹¼ëŸ¼ì´ ì´ë¯¸ ì œê±°ë˜ì—ˆê¸° ë•Œë¬¸ì— **INSERT** ë¬¸ì˜ ì‹¤í–‰ì€ ì‹¤íŒ¨í•œë‹¤. *code* í…Œì´ë¸”ì— ìž…ë ¥í•˜ë ¤ê³ í–ˆë˜ ë°ì´í„°ëŠ” 틀리지 않으나 í…Œì´ë¸”ì—서 ì¹¼ëŸ¼ì´ ìž˜ëª» ì œê±°ë˜ì—ˆë‹¤. ì´ ì‹œì ì—서 *code* í…Œì´ë¸”ì˜ ì›ëž˜ ì •ì˜ë¥¼ ë³µì›í•˜ê¸° 위해서 **ROLLBACK WORK** ë¬¸ì„ ì‚¬ìš©í• ìˆ˜ 있다. .. code-block:: sql ROLLBACK WORK; ì´í›„ì— **ALTER CLASS** ëª…ë ¹ì„ ë‹¤ì‹œ ìž…ë ¥í•˜ì—¬ *s_name* ì¹¼ëŸ¼ì„ ì œê±°í•˜ë©°, **INSERT** ë¬¸ì„ ìˆ˜ì •í•œë‹¤. 트랜ìžì…˜ì´ 중단ë˜ì—ˆê¸° ë•Œë¬¸ì— **INSERT** ëª…ë ¹ì€ ë‹¤ì‹œ ìž…ë ¥ë˜ì–´ì•¼ 한다. ë°ì´í„°ë² ì´ìФ ê°±ì‹ ì´ ì˜ë„한 대로 ì´ë£¨ì–´ì¡Œìœ¼ë©´ ë³€ê²½ì„ ì˜êµ¬í™”하기 위해 트랜ìžì…˜ì„ 커밋한다. .. code-block:: sql ALTER TABLE code2 DROP s_name; INSERT INTO code2 (f_name) VALUES ('Diamond'); COMMIT WORK; 세ì´ë¸Œí¬ì¸íŠ¸ì™€ 부분 롤백 ------------------------ 세ì´ë¸Œí¬ì¸íЏ(savepoint)는 트랜ìžì…˜ì´ ì§„í–‰ë˜ëŠ” ì¤‘ì— ìˆ˜ë¦½ë˜ëŠ”ë°, 트랜ìžì…˜ì— ì˜í•´ 수행ë˜ëŠ” ë°ì´í„°ë² ì´ìФ ê°±ì‹ ì„ ì„¸ì´ë¸Œí¬ì¸íЏ ì§€ì 까지만 ë¡¤ë°±í• ìˆ˜ 있ë„ë¡ í•˜ê¸° 위해서ì´ë‹¤. ì´ ì—°ì‚°ì„ ë¶€ë¶„ 롤백(partial rollback)ì´ë¼ê³ 부른다. 부분 롤백ì—서는 세ì´ë¸Œí¬ì¸íЏ ì´í›„ì˜ ë°ì´í„°ë² ì´ìФ ì—°ì‚°(삽입, ì‚ì œ, ê°±ì‹ ë“±)ì€ í•˜ì§€ ì•Šì€ ê²ƒìœ¼ë¡œ ë˜ê³ 세ì´ë¸Œí¬ì¸íЏ ì§€ì ì„ í¬í•¨í•˜ì—¬ 앞서 ì§„í–‰ëœ íŠ¸ëžœìžì…˜ì˜ ì—°ì‚°ì€ ê·¸ëŒ€ë¡œ ìœ ì§€ëœë‹¤. 부분 ë¡¤ë°±ì´ ì‹¤í–‰ëœ í›„ì— íŠ¸ëžœìžì…˜ì€ 다른 ì—°ì‚°ì„ ê³„ì† ì§„í–‰í• ìˆ˜ 있다. ë˜ëŠ” **COMMIT WORK** 문ì´ë‚˜ **ROLLBACK WORK** 문으로 트랜ìžì…˜ì„ ë낼 ìˆ˜ë„ ìžˆë‹¤. 세ì´ë¸Œí¬ì¸íŠ¸ëŠ” 트랜ìžì…˜ì—서 ìˆ˜í–‰ëœ ê°±ì‹ ì„ ì»¤ë°‹í•˜ëŠ” ê²ƒì´ ì•„ë‹˜ì„ ëª…ì‹¬í•´ì•¼ 한다. 세ì´ë¸Œí¬ì¸íŠ¸ëŠ” 트랜ìžì…˜ì˜ ì–´ëŠ ì‹œì ì—ì„œë„ ë§Œë“¤ 수 ìžˆê³ ëª‡ ê°œì˜ ì„¸ì´ë¸Œí¬ì¸íЏë¼ë„ ì–´ë–¤ 주어진 시ì ì— ì‚¬ìš©ë 수 있다. íŠ¹ì • 세ì´ë¸Œí¬ì¸íŠ¸ë³´ë‹¤ ì•žì„ ì„¸ì´ë¸Œí¬ì¸íŠ¸ë¡œ 부분 ë¡¤ë°±ì´ ìˆ˜í–‰ë˜ê±°ë‚˜ **COMMIT WORK** ë˜ëŠ” **ROLLBACK WORK** 문으로 트랜ìžì…˜ì´ ë나면 íŠ¹ì • 세ì´ë¸Œí¬ì¸íŠ¸ëŠ” ì œê±°ëœë‹¤. íŠ¹ì • 세ì´ë¸Œí¬ì¸íЏ ì´í›„ì— ëŒ€í•œ 부분 ë¡¤ë°±ì€ ì—¬ëŸ¬ 번 수행ë 수 있다. 세ì´ë¸Œí¬ì¸íŠ¸ëŠ” ê¸¸ê³ ë³µìž¡í•œ í”„ë¡œê·¸ëž¨ì„ í†µì œí• ìˆ˜ 있ë„ë¡ ì¤‘ê°„ 단계를 ë§Œë“¤ê³ ì´ë¦„ì„ ë¶™ì¼ ìˆ˜ 있기 ë•Œë¬¸ì— ìœ ìš©í•˜ë‹¤. 예를 들어, ë§Žì€ ê°±ì‹ ì—°ì‚° 수행 시 세ì´ë¸Œí¬ì¸íŠ¸ë¥¼ 사용하면 실수를 í–ˆì„ ë•Œ ëª¨ë“ ë¬¸ìž¥ì„ ë‹¤ì‹œ ìˆ˜í–‰í• í•„ìš”ê°€ 없다. :: SAVEPOINT <mark>; <mark>: - a SQL identifier - a host variable (starting with :) ê°™ì€ íŠ¸ëžœìžì…˜ ë‚´ì— ì—¬ëŸ¬ ê°œì˜ ì„¸ì´ë¸Œí¬ì¸íŠ¸ë¥¼ ì§€ì •í• ë•Œ *mark* 를 ê°™ì€ ê°’ìœ¼ë¡œ 하면 마지막 세ì´ë¸Œí¬ì¸íŠ¸ë§Œ 부분 ë¡¤ë°±ì— ë‚˜íƒ€ë‚œë‹¤. ê·¸ë¦¬ê³ ì•žì˜ ì„¸ì´ë¸Œí¬ì¸íŠ¸ëŠ” ì œì¼ ë§ˆì§€ë§‰ 세ì´ë¸Œí¬ì¸íŠ¸ë¡œ 부분 ë¡¤ë°±í• ë•Œê¹Œì§€ ê°ì¶°ì¡Œë‹¤ê°€ ì œì¼ ë§ˆì§€ë§‰ 세ì´ë¸Œí¬ì¸íŠ¸ê°€ ì‚¬ìš©ëœ í›„ 없어지면 나타난다. :: ROLLBACK [WORK] [TO [SAVEPOINT] <mark> ; <mark>: - a SQL identifier - a host variable (starting with :) 앞ì—서는 **ROLLBACK WORK** ë¬¸ì´ ë§ˆì§€ë§‰ 트랜ìžì…˜ ì´í›„로 ìž…ë ¥ëœ ëª¨ë“ ë°ì´í„°ë² ì´ìŠ¤ì˜ ê°±ì‹ ì„ ì œê±°í•˜ì˜€ë‹¤. **ROLLBACK WORK** ë¬¸ì€ íŠ¹ì • 세ì´ë¸Œí¬ì¸íЏ ì´í›„로 트랜ìžì…˜ì˜ ê°±ì‹ ì„ ë˜ëŒë¦¬ëŠ” 부분 롤백ì—ë„ ì‚¬ìš©ëœë‹¤. *mark* ì˜ ê°’ì´ ì£¼ì–´ì§€ì§€ 않으면 트랜ìžì…˜ì€ ëª¨ë“ ê°±ì‹ ì„ ì·¨ì†Œí•˜ë©´ì„œ 종료한다. 여기ì—는 트랜ìžì…˜ì— 만들어진 ëª¨ë“ ì„¸ì´ë¸Œí¬ì¸íŠ¸ë„ í¬í•¨í•œë‹¤. *mark* ê°€ 주어지면 ì§€ì •í•œ 세ì´ë¸Œí¬ì¸íЏ ì´í›„ì˜ ê²ƒì€ ì·¨ì†Œë˜ê³ , 세ì´ë¸Œí¬ì¸íŠ¸ë¥¼ í¬í•¨í•œ ì´ì „ì˜ ê²ƒì€ ê°±ì‹ ì‚¬í•ì´ ë‚¨ëŠ”ë‹¤. ë‹¤ìŒ ì˜ˆì œëŠ” 트랜ìžì…˜ì˜ ì¼ë¶€ë¥¼ 롤백하는 ë°©ë²•ì„ ë³´ì—¬ì¤€ë‹¤. ë¨¼ì € savepoint *SP1*, *SP2* 를 ì„¤ì •í•œë‹¤. .. code-block:: sql -- csql> ;autocommit off CREATE TABLE athlete2 (name VARCHAR(40), gender CHAR(1), nation_code CHAR(3), event VARCHAR(30)); INSERT INTO athlete2(name, gender, nation_code, event) VALUES ('Lim Kye-Sook', 'W', 'KOR', 'Hockey'); SAVEPOINT SP1; SELECT * from athlete2; INSERT INTO athlete2(name, gender, nation_code, event) VALUES ('Lim Jin-Suk', 'M', 'KOR', 'Handball'); SELECT * FROM athlete2; SAVEPOINT SP2; RENAME TABLE athlete2 AS sportsman; SELECT * FROM sportsman; ROLLBACK WORK TO SP2; 위ì—서 *athlete2* í…Œì´ë¸”ì˜ ì´ë¦„ ë³€ê²½ì€ ìœ„ì˜ ë¶€ë¶„ ë¡¤ë°±ì— ì˜í•´ì„œ 롤백ëœë‹¤. 다ìŒì˜ ë¬¸ìž¥ì€ ì›ëž˜ì˜ ì´ë¦„으로 질ì˜ë¥¼ 수행하여 ì´ê²ƒì„ ê²€ì¦í•˜ê³ 있다. .. code-block:: sql SELECT * FROM athlete2; DELETE FROM athlete2 WHERE name = 'Lim Jin-Suk'; SELECT * FROM athlete2; ROLLBACK WORK TO SP2; 위ì—서 'Lim Jin-Suk' ì„ ì‚ì œí•œ ê²ƒì€ ì´í›„ì— ì§„í–‰ë˜ëŠ” rollback work to *SP2* ëª…ë ¹ë¬¸ì— ì˜í•´ì„œ 취소ë˜ì—ˆë‹¤. 다ìŒì€ *SP1* 으로 롤백하는 경우ì´ë‹¤. .. code-block:: sql SELECT * FROM athlete2; ROLLBACK WORK TO SP1; SELECT * FROM athlete2; COMMIT WORK; .. _cursor-holding: 커서 ìœ ì§€ ========= ì‘ìš© í”„ë¡œê·¸ëž¨ì´ ëª…ì‹œì ì¸ ì»¤ë°‹ í˜¹ì€ ìžë™ 커밋 ì´í›„ì—ë„ **SELECT** ì§ˆì˜ ê²°ê³¼ì˜ ë ˆì½”ë“œì…‹ì„ ìœ ì§€í•˜ì—¬ ë‹¤ìŒ ë ˆì½”ë“œë¥¼ ì½ì„(fetch) 수 있ë„ë¡ í•˜ëŠ” ê²ƒì„ ì»¤ì„œ ìœ ì§€(cursor holdability)ë¼ê³ 한다. ê° ì‘ìš© 프로그램ì—서 ì—°ê²° 수준(connection level) ë˜ëŠ” 문장 수준(statement level)으로 커서 ìœ ì§€ ê¸°ëŠ¥ì„ ì„¤ì •í• ìˆ˜ 있으며, ì„¤ì •ì„ ëª…ì‹œí•˜ì§€ 않으면 기본으로 커서가 ìœ ì§€ëœë‹¤. ë‹¤ìŒ ì½”ë“œëŠ” JDBCì—서 커서 ìœ ì§€ë¥¼ ì„¤ì •í•˜ëŠ” 예ì´ë‹¤. .. code-block:: java // set cursor holdability at the connection level conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); // set cursor holdability at the statement level which can override the connection PreparedStatement pStmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT); 커밋 시ì ì— ì»¤ì„œë¥¼ ìœ ì§€í•˜ì§€ ì•Šê³ ì»¤ì„œë¥¼ ë‹«ë„ë¡ ì„¤ì •í•˜ê³ ì‹¶ìœ¼ë©´, ìœ„ì˜ ì˜ˆì œì—서 **ResultSet.HOLD_CURSORS_OVER_COMMIT** ëŒ€ì‹ **ResultSet.CLOSE_CURSORS_AT_COMMIT** 를 ì„¤ì •í•œë‹¤. CCI 로 ê°œë°œëœ ì‘ìš© 프로그램 ì—시 커서 ìœ ì§€ê°€ 기본 ë™ìž‘ì´ë©°, ì—°ê²° 수준ì—서 커서를 ìœ ì§€í•˜ì§€ 않ë„ë¡ ì„¤ì •í•œ 경우 질ì˜ë¥¼ prepareí• ë•Œ **CCI_PREPARE_HOLDABLE** 플래그를 명시하면 해당 ì§ˆì˜ ìˆ˜ì¤€ì—서 커서를 ìœ ì§€í•œë‹¤. CCI로 ê°œë°œëœ ë“œë¼ì´ë²„(PHP, PDO, ODBC, OLE DB, ADO.NET, Perl, Python, Ruby) ì—시 커서 ìœ ì§€ê°€ 기본 ë™ìž‘ì´ë©°, 커서 ìœ ì§€ ì—¬ë¶€ì˜ ì„¤ì •ì„ ì§€ì›í•˜ëŠ”ì§€ì— ëŒ€í•´ì„œëŠ” 해당 드ë¼ì´ë²„ì˜ **PREPARE** 함수를 ì°¸ê³ í•œë‹¤. .. note:: * CUBRID 9.0 미만 ë²„ì „ê¹Œì§€ëŠ” 커서 ìœ ì§€ë¥¼ ì§€ì›í•˜ì§€ 않으며, ì»¤ë°‹ì´ ë°œìƒí•˜ë©´ 커서가 ìžë™ìœ¼ë¡œ 닫히는 ê²ƒì´ ê¸°ë³¸ ë™ìž‘ì´ë‹¤. * CUBRID는 현재 java.sql.XAConnection ì¸í„°íŽ˜ì´ìФì—서 ResultSet.HOLD_CURSORS_OVER_COMMITì„ ì§€ì›í•˜ì§€ 않는다. **트랜ìžì…˜ 종료 ì‹œì˜ ì»¤ì„œ ê´€ë ¨ ë™ìž‘** 트랜ìžì…˜ì´ 커밋ë˜ë©´ 커서 ìœ ì§€ë¡œ ì„¤ì •ë˜ì–´ 있ë”ë¼ë„ ëª¨ë“ ìž ê¸ˆì€ í•´ì œëœë‹¤. 트랜ìžì…˜ì´ 롤백ë˜ë©´ ê²°ê³¼ ì…‹ì´ ë‹«ížŒë‹¤. ì´ê²ƒì€ 커서 ìœ ì§€ê°€ ì„¤ì •ë˜ì–´ 현재 트랜ìžì…˜ì—서 ìœ ì§€ë˜ë˜ ê²°ê³¼ ì…‹ì´ ë‹«ížŒë‹¤ëŠ” ê²ƒì„ ì˜ë¯¸í•œë‹¤. .. code-block:: java rs1 = stmt.executeQuery(sql1); conn.commit(); rs2 = stmt.executeQuery(sql2); conn.rollback(); // ê²°ê³¼ ì…‹ rs2와 rs1ì´ ë‹«ížˆê²Œ ë˜ì–´ 둘 다 사용하지 못하게 ë¨. **ê²°ê³¼ ì…‹ì´ ì¢…ë£Œë˜ëŠ” 경우** 커서가 ìœ ì§€ë˜ëŠ” ê²°ê³¼ ì…‹ì€ ë‹¤ìŒì˜ ê²½ìš°ì— ë‹«ížŒë‹¤. * 드ë¼ì´ë²„ì—서 ê²°ê³¼ ì…‹ì„ ë‹«ëŠ” 경우(예: rs.close() 등) * 드ë¼ì´ë²„ì—서 statement를 닫는 경우(예: stmt.close() 등) * 드ë¼ì´ë²„ ì—°ê²° 종료 * 트랜ìžì…˜ì„ 롤백하는 경우(예: ìžë™ 커밋 OFF 모드ì—서 사용ìžì˜ 명시ì ì¸ ë¡¤ë°± 호출, ìžë™ 커밋 ON 모드ì—서 ì§ˆì˜ ì‹¤í–‰ 오류 ë°œìƒ ë“±) **CASì™€ì˜ ê´€ê³„** ì‘ìš© 프로그램ì—서 커서 ìœ ì§€ë¡œ ì„¤ì •ë˜ì–´ ìžˆë‹¤ê³ í•´ë„ ì‘ìš© 프로그램과 CASì™€ì˜ ì—°ê²°ì´ ëŠê¸°ë©´ ê²°ê³¼ ì…‹ì€ ìžë™ìœ¼ë¡œ 닫힌다. 브로커 파ë¼ë¯¸í„°ì¸ **KEEP_CONNECTION** ì˜ ì„¤ì • ê°’ì€ ê²°ê³¼ ì…‹ì˜ ì»¤ì„œ ìœ ì§€ì— ì˜í–¥ì„ 미친다. * KEEP_CONNECTION = ON: 커서 ìœ ì§€ì— ì˜í–¥ì„ 주지 않ìŒ. * KEEP_CONNECTION = AUTO: 커서 ìœ ì§€ë˜ëŠ” ê²°ê³¼ ì…‹ì´ ì—´ë ¤ 있는 ë™ì•ˆ CASê°€ 재시작ë 수 ì—†ìŒ. .. warning:: ê²°ê³¼ ì…‹ì„ ë‹«ì§€ ì•Šì€ ìƒíƒœë¡œ ìœ ì§€í•˜ëŠ” ë§Œí¼ ë©”ëª¨ë¦¬ ì‚¬ìš©ëŸ‰ì´ ëŠ˜ì–´ë‚ ìˆ˜ 있으므로 ì‚¬ìš©ì„ ë§ˆì¹œ ê²°ê³¼ ì…‹ì€ ë°˜ë“œì‹œ 닫아야 한다. .. note:: CUBRID 9.0 미만 ë²„ì „ê¹Œì§€ëŠ” 커서 ìœ ì§€ë¥¼ ì§€ì›í•˜ì§€ 않으며, ì»¤ë°‹ì´ ë°œìƒí•˜ë©´ 커서가 ìžë™ìœ¼ë¡œ 닫힌다. 즉, **SELECT** ì§ˆì˜ ê²°ê³¼ì˜ ë ˆì½”ë“œì…‹ì„ ìœ ì§€í•˜ì§€ 않는다. .. _database-concurrency: ë°ì´í„°ë² ì´ìФ ë™ì‹œì„± =================== ë‹¤ìˆ˜ì˜ ì‚¬ìš©ìžë“¤ì´ ë°ì´í„°ë² ì´ìФì—서 ì½ê³ 쓰는 ê¶Œí•œì„ ê°€ì§ˆ 때, 한 명 ì´ìƒì˜ 사용ìžê°€ ë™ì‹œì— ê°™ì€ ë°ì´í„°ì— ì ‘ê·¼í• ê°€ëŠ¥ì„±ì´ ìžˆë‹¤. ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¬´ê²°ì„±ì„ ë³´í˜¸í•˜ê³ , 사용ìžì™€ 트랜ìžì…˜ì´ í•ìƒ ì •í™•í•˜ê³ ì¼ê´€ëœ ë°ì´í„°ë¥¼ 지니기 위해서는 다중 ì‚¬ìš©ìž í™˜ê²½ì—ì„œì˜ ì ‘ê·¼ê³¼ ê°±ì‹ ì— ëŒ€í•œ í†µì œê°€ 필수ì ì´ë‹¤. ì ì •í•œ í†µì œê°€ 없으면 ë°ì´í„°ëŠ” 어긋난 순서로 ë¶€ì •í™•í•˜ê²Œ ê°±ì‹ ë 수 있다. 트랜ìžì…˜ì€ ë°ì´í„°ë² ì´ìФ ë™ì‹œì„±ì„ 보장해야하며 ê° íŠ¸ëžœìžì…˜ì€ ì ì ˆí•œ 결과를 보장해야한다. 한 ë²ˆì— ì—¬ëŸ¬ 트랜ìžì…˜ì´ 실행ë 때 트랜ìžì…˜ *T1* ì˜ ì´ë²¤íŠ¸ê°€ 트랜ìžì…˜ *T2* ì˜ ì´ë²¤íŠ¸ì— ì˜í–¥ì„ 미치지 않아야 한다. ì´ê²ƒì€ 격리를 ì˜ë¯¸í•œë‹¤. 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì€ íŠ¸ëžœìžì…˜ì´ 다른 ëª¨ë“ ë™ì‹œ 트랜ìžì…˜ê³¼ 분리ë˜ëŠ” ì •ë„ì´ë‹¤. 격리 ìˆ˜ì¤€ì´ ë†’ìœ¼ë©´ 다른 트랜ìžì…˜ì˜ ê°„ì„ì´ ì ìŒì„ ì˜ë¯¸í•œë‹¤. 격리 ìˆ˜ì¤€ì´ ë‚®ìœ¼ë©´ ë™ì‹œì„±ì´ 높다는 ê²ƒì„ ì˜ë¯¸í•œë‹¤. ë°ì´í„°ë² ì´ìŠ¤ëŠ” 격리 ë ˆë²¨ì— ë”°ë¼ ì–´ë–¤ ìž ê¸ˆ(lock)ì´ í…Œì´ë¸”ê³¼ ë ˆì½”ë“œì— ì ìš©í• ê²ƒì¸ì§€ íŒë³„한다. ë”°ë¼ì„œ ì ì ˆí•œ 격리 ìˆ˜ì¤€ì„ ì„¤ì •í•˜ì—¬ 서비스 ê³ ìœ ì˜ ì¼ê´€ì„± ë° ë™ì‹œì„± ìˆ˜ì¤€ì„ ì œì–´ í• ìˆ˜ 있다. 트랜ìžì…˜ 격리 수준 ì„¤ì •ì„ í†µí•´ 트랜ìžì…˜ ê°„ ê°„ì„ì„ í—ˆìš©í• ìˆ˜ 있는 ì½ê¸° ì—°ì‚°ì˜ ì¢…ë¥˜ëŠ” 다ìŒê³¼ 같다. * **ë”í‹° ì½ê¸° (Dirty read)** : 트랜ìžì…˜ *T1* ì´ ë°ì´í„° *D* 를 *D'* 으로 ê°±ì‹ í•œ 후 ì»¤ë°‹ì„ ìˆ˜í–‰í•˜ê¸° ì „ì— íŠ¸ëžœìžì…˜ *T2* ê°€ *D'* ì„ ì½ì„ 수 있다. * **ë°˜ë³µí• ìˆ˜ 없는 ì½ê¸° (Non-repeatable read)** : 트랜ìžì…˜ *T1* ì´ ë°ì´í„°ë¥¼ 반복 조회하는 ì¤‘ì— ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ê°€ ë°ì´í„°ë¥¼ ê°±ì‹ í˜¹ì€ ì‚ì œí•˜ê³ ì»¤ë°‹í•˜ëŠ” 경우, 트랜ìžì…˜ *T1* ì€ ìˆ˜ì •ëœ ê°’ì„ ì½ì„ 수 있다. * **ìœ ë ¹ ì½ê¸° (Phantom read)** : 트랜ìžì…˜ *T1* ì—서 ë°ì´í„°ë¥¼ 여러 번 조회하는 ì¤‘ì— ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ê°€ 새로운 ë ˆì½”ë“œ *E* 를 ì‚½ìž…í•˜ê³ ì»¤ë°‹í•œ 경우, 트랜ìžì…˜ *T1* ì€ *E* 를 ì½ì„ 수 있다. ì´ëŸ¬í•œ ê°„ì„ì„ ê¸°ë°˜ìœ¼ë¡œ SQL í‘œì¤€ì€ íŠ¸ëžœìžì…˜ 격리 ìˆ˜ì¤€ì„ ë„¤ 가지로 ì •ì˜í•œë‹¤. * **READ UNCOMMITTED** 는 ë”í‹° ì½ê¸°(dirty read), ë°˜ë³µí• ìˆ˜ 없는 ì½ê¸°(unrepeatable read), ìœ ë ¹ ì½ê¸°(phantom read)를 허용한다. * **READ COMMITTED** 는 ë”í‹° ì½ê¸°ë¥¼ 허용하지 않으며 ë°˜ë³µí• ìˆ˜ 없는 ì½ê¸°ì™€ ìœ ë ¹ ì½ê¸°ë¥¼ 허용한다. * **REPEATABLE READ** 는 ë”í‹° ì½ê¸°ì™€ ë°˜ë³µí• ìˆ˜ 없는 ì½ê¸°ë¥¼ 허용하지 않으며 ìœ ë ¹ ì½ê¸°ë¥¼ 허용한다. * **SERIALIZABLE** ì€ ì½ê¸° ì—°ì‚° 시 트랜ìžì…˜ ê°„ ê°„ì„ì„ í—ˆìš©í•˜ì§€ 않는다. **CUBRIDê°€ ì œê³µí•˜ëŠ” 격리 수준** 아래 표ì—서 격리 수준 ì˜†ì— ìžˆëŠ” 괄호 ì•ˆì˜ ìˆ«ìžëŠ” 격리 ìˆ˜ì¤€ì„ ì„¤ì •í• ë•Œ 격리 수준 ëª…ì¹ ëŒ€ì‹ ì‚¬ìš©í• ìˆ˜ 있는 번호ì´ë‹¤. 사용ìžëŠ” :ref:`set-transaction-isolation-level` ë¬¸ì„ ì‚¬ìš©í•˜ê±°ë‚˜ CUBRIDê°€ ì§€ì›í•˜ëŠ” ë™ì‹œì„±/ìž ê¸ˆ 파ë¼ë¯¸í„°ë¥¼ ì´ìš©í•˜ì—¬ 격리 ìˆ˜ì¤€ì„ ì„¤ì •í• ìˆ˜ 있는ë°, ì´ì— 관한 ì„¤ëª…ì€ :ref:`lock-parameters`\ 를 참조한다. (O: YES, X: NO) +--------------------------------+--------+-----------+--------+----------------------+ | CUBRID 격리 수준 | ë”í‹° | ë°˜ë³µí• ìˆ˜ | ìœ ë ¹ | 조회 ì¤‘ì¸ í…Œì´ë¸”ì— | | (isolation_level) | ì½ê¸° | 없는 ì½ê¸° | ì½ê¸° | 대한 스키마 ê°±ì‹ | +================================+========+===========+========+======================+ | :ref:`isolation-level-6` (6) | X | X | X | X | +--------------------------------+--------+-----------+--------+----------------------+ | :ref:`isolation-level-5` (5) | X | X | O | X | +--------------------------------+--------+-----------+--------+----------------------+ | :ref:`isolation-level-4` (4) | X | O | O | X | +--------------------------------+--------+-----------+--------+----------------------+ CUBRID 격리 ìˆ˜ì¤€ì˜ ê¸°ë³¸ê°’ì€ :ref:`isolation-level-4` ì´ë‹¤. .. _mvcc-snapshot: 다중 ë²„ì „ ë™ì‹œì„± ì œì–´(Multiversion Concurrency Control) ======================================================= ì´ì „ CUBRID는 잘 ì•Œë ¤ì§„ 2단계 ìž ê¸ˆ í”„ë¡œí† ì½œì„ ì‚¬ìš©í•˜ì—¬ 격리 ìˆ˜ì¤€ì„ ê´€ë¦¬í–ˆë‹¤. ì´ í”„ë¡œí† ì½œì—서는 ë™ì‹œì— ì—°ì‚° ì¶©ëŒì´ ë°œìƒí•˜ì§€ 않ë„ë¡ íŠ¸ëžœìžì…˜ì´ ê°ì²´ë¥¼ ì½ê¸° ì „ì— ê³µìœ ìž ê¸ˆì„ íšë“í•˜ê³ , ê°±ì‹ í•˜ê¸° ì „ì— ë°°íƒ€ ìž ê¸ˆì„ íšë“한다. 트랜ìžì…˜ *T1* ì— ìž ê¸ˆì´ í•„ìš”í•œ 경우 시스템ì—서 ìš”ì²ëœ ìž ê¸ˆì´ ê¸°ì¡´ ìž ê¸ˆê³¼ ì¶©ëŒí•˜ëŠ”ì§€ 확ì¸í•œë‹¤. ì¶©ëŒì´ ë°œìƒí•˜ë©´ 트랜ìžì…˜ *T1* ì€ ëŒ€ê¸° ìƒíƒœê°€ ë˜ê³ ìž ê¸ˆì´ ì§€ì—°ëœë‹¤. 다른 트랜ìžì…˜ *T2* ê°€ ìž ê¸ˆì„ í•´ì œí•˜ë©´ 트랜ìžì…˜ *T1* ì´ ë‹¤ì‹œ 시작ë˜ì–´ ìž ê¸ˆì„ íšë“한다. ìž ê¸ˆì´ í•´ì œë˜ë©´ 해당 트랜ìžì…˜ì—서 새로운 ìž ê¸ˆì„ íšë“í• í•„ìš”ê°€ 없다. CUBRID 10.0ì—서는 2단계 ìž ê¸ˆ í”„ë¡œí† ì½œì´ Multiversion Concurrency Control(MVCC) í”„ë¡œí† ì½œë¡œ 대체ë˜ì—ˆë‹¤. 2단계 ìž ê¸ˆ í”„ë¡œí† ì½œê³¼ 달리, MVCC는 ë™ì‹œ 트랜ìžì…˜ì—서 ìˆ˜ì • ì¤‘ì¸ ê°ì²´ì— 액세스하여 ì½ëŠ” ê²ƒì„ í—ˆìš©í•œë‹¤. MVCC는 í–‰ì„ ì¤‘ë³µí•˜ì—¬ ê°±ì‹ ë 때마다 여러 ë²„ì „ì„ ìƒì„±í•œë‹¤. 주로 ë°ì´í„°ë² ì´ìФì—서 ì½ê¸° ì—°ì‚°ì´ ë§Žì€ ì‹œë‚˜ë¦¬ì˜¤ì— ëŒ€í•´ì„œëŠ” ì½ê¸° ì—°ì‚°ì„ í—ˆìš©í•˜ëŠ” ê²ƒì´ ì¤‘ìš”í•˜ë‹¤. ê°ì²´ë¥¼ ê°±ì‹ í•˜ê¸° ì „ì—는 ì—¬ì „ížˆ 배타 ìž ê¸ˆì´ í•„ìš”í•˜ë‹¤. MVCC는 ë°ì´í„°ë² ì´ìŠ¤ì˜ ì¼ê´€ëœ 시ì ì„ ì œê³µí•˜ë©°, 특히 다른 ë™ì‹œì„± 방법보다 ì ì€ ì„±ëŠ¥ 비용으로 ì§„ì •í•œ **snapshot isolation** ì„ êµ¬í˜„í• ìˆ˜ 있다. ë²„ì „ 관리, 가시성 ë° ìŠ¤ëƒ…ìƒ· --------------------------- MVCC는 ê° ë°ì´í„°ë² ì´ìФ í–‰ì— ëŒ€í•´ 여러 ë²„ì „ì„ ìœ ì§€í•œë‹¤. ê° ë²„ì „ë§ˆë‹¤ MVCCID(쓰기 트랜ìžì…˜ì— 대한 ê³ ìœ ì‹ë³„ìž)로 삽입ìž(inserter) ë° ì‚ì œìž(deleter)ê°€ 표시ëœë‹¤. ì´ëŸ¬í•œ 마커(Marker)는 변경한 사용ìžë¥¼ íŒŒì•…í•˜ê³ íƒ€ìž„ë¼ì¸ì— 변경 사í•ì„ í‘œì‹œí•˜ëŠ” ë° ìœ ìš©í•˜ë‹¤. 트랜ìžì…˜ *T1* ì´ ìƒˆë¡œìš´ í–‰ì„ ì‚½ìž…í•˜ë©´ 첫 번째 ë²„ì „ì´ ìƒì„±ë˜ê³ ê³ ìœ ì‹ë³„ìž *MVCCID1* ì´ ì‚½ìž… ID로 ì„¤ì •ëœë‹¤. MVCCID는 ë ˆì½”ë“œ í—¤ë”ì— ë©”íƒ€ë°ì´í„°ë¡œ ì €ìž¥ëœë‹¤. +------------------+-------------+---------------+ | OTHER META-DATA | MVCCID1 | RECORD DATA | +------------------+-------------+---------------+ *T1* ì´ ì»¤ë°‹í• ë•Œê¹Œì§€ 다른 트랜ìžì…˜ì—서는 *T1* ì´ ì‚½ìž…í•œ í–‰ì„ ë³¼ 수 없어야 한다. MVCCID는 ë°ì´í„°ë² ì´ìФ 변경 사í•ì˜ ìž‘ì„±ìžë¥¼ ì‹ë³„í•˜ê³ íƒ€ìž„ ë¼ì¸ì— 배치하여 다른 트랜ìžì…˜ì´ 변경 사í•ì˜ ìœ íš¨ì„±ì„ ì•Œ 수 있ë„ë¡ í•œë‹¤. ì´ ê²½ìš° ì´ í–‰ì„ ê²€ì‚¬í•˜ëŠ” ëª¨ë“ íŠ¸ëžœìžì…˜ì€ *MVCCID1* ì„ ì°¾ê³ ì†Œìœ ìžê°€ ì—¬ì „ížˆ 활성 ìƒíƒœì´ë¯€ë¡œ ì´ í–‰ì„ ë³¼ 수 없다. *T1* ì´ ì»¤ë°‹ ëœ í›„ 새로운 트랜ìžì…˜ *T2* ê°€ í–‰ì„ ì°¾ì•„ ì œê±°í•œë‹¤. *T2* 는 배타 ìž ê¸ˆì„ íšë“하는 ëŒ€ì‹ , 다른 트랜ìžì…˜ì´ ì•¡ì„¸ìŠ¤í• ìˆ˜ 있ë„ë¡ í•´ë‹¹ ë²„ì „ì„ ì œê±°í•˜ì§€ ì•Šì€ ìƒíƒœë¡œ ë‘ê³ , 다른 트랜ìžì…˜ì´ ë³€ê²½í• ìˆ˜ ì—†ë„ë¡ ë²„ì „ì„ ì‚ì œë¨ìœ¼ë¡œ 표시한다. 다른 MVCCID를 추가하여 다른 트랜ìžì…˜ì´ ì‚ì œìžë¥¼ ì‹ë³„ í• ìˆ˜ 있ë„ë¡ í•œë‹¤. +------------------+-------------+---------------+---------------+ | OTHER META-DATA | MVCCID1 | MVCCID2 | RECORD DATA | +------------------+-------------+---------------+---------------+ *T2* ê°€ ë ˆì½”ë“œ ê°’ 중 하나를 ê°±ì‹ í•˜ê¸°ë¡œ ê²°ì •í•˜ë©´ í–‰ì„ ì‹ ê·œ ë²„ì „ìœ¼ë¡œ ê°±ì‹ í•˜ê³ ì´ì „ ë²„ì „ì„ ë¡œê·¸ì— ì €ìž¥í•´ì•¼ 한다. 새로운 í–‰ì€ ìƒˆë¡œìš´ ë°ì´í„°, 트랜ìžì…˜ MVCCID(삽입 MVCCID) ë° ì´ì „ ë²„ì „ì´ ì €ìž¥ëœ ë¡œê·¸ ì—”íŠ¸ë¦¬ì˜ ì£¼ì†Œë¡œ 구성ëœë‹¤. í–‰ì— í‘œì‹œë˜ëŠ” ë‚´ìš©ì€ ë‹¤ìŒê³¼ 같다. *HEAP* 파ì¼ì€ OIDì— ì˜í•´ ì‹ë³„ë˜ëŠ” ë‹¨ì¼ í–‰ì„ í¬í•¨í•œë‹¤. +------------------+-------------+--------------------+---------------+ | OTHER META-DATA | MVCCID_INS1 | PREV_VERSION_LSA1 | RECORD DATA | +------------------+-------------+--------------------+---------------+ LOG 파ì¼ì—는 로그 엔트리 ì²´ì¸ì´ ìžˆê³ , ê° ë¡œê·¸ ì—”íŠ¸ë¦¬ì˜ ì–¸ë‘ ë¶€ë¶„ì€ ìˆ˜ì •ë˜ê¸° ì „ì˜ íž™ ë ˆì½”ë“œë¥¼ í¬í•¨í•œë‹¤. +----------------------+------------------+-------------+--------------------+---------------+ | LOG ENTRY META-DATA | OTHER META-DATA | MVCCID_INS2 | PREV_VERSION_LSA2 | RECORD DATA | +----------------------+------------------+-------------+--------------------+---------------+ +----------------------+------------------+-------------+--------------------+---------------+ | LOG ENTRY META-DATA | OTHER META-DATA | MVCCID_INS3 | NULL | RECORD DATA | +----------------------+------------------+-------------+--------------------+---------------+ 다른 트랜ìžì…˜ì€ ê° ë ˆì½”ë“œì˜ ì‚½ìž… ë° ì‚ì œ MVCCID ê°’ì— ë”°ë¼ ê²°ì •ë˜ëŠ” 가시성 ì¡°ê±´ì„ ë§Œì¡±í•˜ëŠ” ë ˆì½”ë“œê°€ 나올 때까지 다중 로그 ë ˆì½”ë“œì˜ ì´ì „ ë²„ì „ LSAì˜ ë¡œê·¸ ì²´ì¸ì„ ì¡°ì‚¬í• í•„ìš”ê°€ 있다. .. note:: * ì˜ˆì „ ë²„ì „(10.0)ì—서는 ê°±ì‹ ëœ í–‰ì˜ ì´ì „ ë° ìƒˆ ë²„ì „ì„ ì €ìž¥í•˜ëŠ” ë° íž™(다른 OID)ì´ ì‚¬ìš©ë˜ì—ˆë‹¤. ì‹¤ì œë¡œ ì´ì „ ë²„ì „ì€ ë³€ê²½ë˜ì§€ ì•Šì€ í–‰ì´ì—ˆìœ¼ë©°, 여기ì—는 새 ë²„ì „ì— ëŒ€í•œ OID ë§í¬ê°€ 추가ë˜ì—ˆë‹¤. 새 ë²„ì „ê³¼ ì´ì „ ë²„ì „ì´ ë‘˜ 다 íž™ì— ì €ìž¥ë˜ì—ˆë‹¤. *T2* ë§Œ ê°±ì‹ ëœ í–‰ì„ ë³¼ 수 있으며, 다른 트랜ìžì…˜ì€ íž™ í–‰ì—서 íšë“한 LSA를 통해 로그 페ì´ì§€ì— 있는 í–‰ ë²„ì „ì— ì•¡ì„¸ìŠ¤í• ìˆ˜ 있다. 실행 ì¤‘ì¸ íŠ¸ëžœìžì…˜ì— ì˜í•´ ë³´ì´ê±°ë‚˜ ë³´ì´ì§€ 않는 ë²„ì „ ì†ì„±ì„ **가시성 (visibility)** ì´ë¼ 한다. 가시성 ì†ì„±ì€ ê° íŠ¸ëžœìžì…˜ê³¼ ê´€ë ¨ì´ ìžˆê³ , ì¼ë¶€ 트랜ìžì…˜ì€ ì´ë¥¼ true로 간주하지만, 나머지 트랜ìžì…˜ì€ false로 ê°„ì£¼í• ìˆ˜ 있다. *T2* ê°€ í–‰ ê°±ì‹ ì„ ìˆ˜í–‰í•œ 후 커밋하기 ì „, 트랜ìžì…˜ *T3* ê°€ 시작한 경우 *T2* ê°€ 커밋한 후ì—ë„ *T3* 는 새 ë²„ì „ì„ ë³¼ 수 없다. *T3* ì˜ ë²„ì „ ê°€ì‹œì„±ì€ *T3* ê°€ ì‹œìž‘í• ë•Œ ì‚½ìž…ìž ë° ì‚ì œìžì˜ ìƒíƒœì— ë”°ë¼ ê²°ì •ë˜ë©°, *T3* ì˜ íŠ¸ëžœìžì…˜ì´ 수행ë˜ëŠ” ë™ì•ˆ 해당 ìƒíƒœê°€ ìœ ì§€ëœë‹¤. 사실ìƒ, 트랜ìžì…˜ì— 대한 ëª¨ë“ ë²„ì „ì˜ ê°€ì‹œì„±ì€ íŠ¸ëžœìžì…˜ì´ ì‹œìž‘ëœ ì´í›„ì— ë°œìƒí•˜ëŠ” 변경 사í•ì˜ ì˜í–¥ì„ 받지 않는다. ë˜í•œ 새로 추가ë˜ëŠ” ë²„ì „ë„ ë¬´ì‹œëœë‹¤. ê²°ê³¼ì 으로 트랜ìžì…˜ì—서 보여진 ë²„ì „ ì…‹ì€ ë³€ê²½ë˜ì§€ ì•Šê³ íŠ¸ëžœìžì…˜ì˜ 스냅샷으로 구성ëœë‹¤. ë”°ë¼ì„œ MVCCì— ì˜í•´ ì œê³µëœ **snapshot isolation** 는 트랜ìžì…˜ì˜ ëª¨ë“ ì½ê¸° 질ì˜ì— 대해 ì¼ê´€ëœ 뷰를 보장한다. CUBRIDì—서 **스냅샷 (snapshot)** ì€ ëª¨ë“ ìœ íš¨í•˜ì§€ ì•Šì€ MVCCIDì˜ í•„í„°ì´ë‹¤. ìŠ¤ëƒ…ìƒ·ì´ ë§Œë“¤ì–´ì§€ê¸° ì „ì— ì»¤ë°‹ë˜ì§€ 않으면 MVCCID는 ìœ íš¨í•˜ì§€ 않다. 새 트랜ìžì…˜ì„ ì‹œìž‘í• ë•Œë§ˆë‹¤ 스냅샷 í•„í„°ê°€ ê°±ì‹ ë˜ì§€ 않기 위해 ë‘ ê²½ê³„(가장 ë‚®ì€ í™œì„± MVCCID와 가장 ë†’ì€ ì»¤ë°‹ MVCCID)를 통해 ìŠ¤ëƒ…ìƒ·ì´ ì •ì˜ëœë‹¤. ì´ ê²½ê³„ ì•ˆì— ìžˆëŠ” 활성 MVCCID ê°’ 목ë¡ë§Œ ì €ìž¥ëœë‹¤. 스냅샷 ì´í›„ ì‹œìž‘ëœ íŠ¸ëžœìžì…˜ì€ 가장 ë†’ì€ ì»¤ë°‹ MVCCID보다 í° MVCCID를 가지므로 ìžë™ìœ¼ë¡œ 무효화ëœë‹¤. 가장 ë‚®ì€ í™œì„± MVCCID보다 ë‚®ì€ MVCCID는 ì´ë¯¸ 커밋ë˜ì—ˆìœ¼ë¯€ë¡œ ìžë™ìœ¼ë¡œ ìœ íš¨í•˜ë‹¤. ë²„ì „ ê°€ì‹œì„±ì„ ê²°ì •í•˜ëŠ” 스냅샷 í•„í„° ì•Œê³ ë¦¬ì¦˜ì€ ì‚½ìž… ë° ì‚ì œì— ì‚¬ìš©ë˜ëŠ” MVCCID 마커를 사용한다. ìŠ¤ëƒ…ìƒ·ì€ íž™ì— ì €ìž¥ëœ ë§ˆì§€ë§‰ ë²„ì „ì„ ê²€ì‚¬í•˜ê³ ê²°ê³¼ì— ë”°ë¼ íž™ì—서 ë²„ì „ì„ ê°€ì ¸ì˜¤ê±°ë‚˜ 로그ì—서 ì´ì „ ë²„ì „ì„ ê°€ì ¸ì˜¬ 수 있으며 í–‰ì„ ë¬´ì‹œí• ìˆ˜ ë„ ìžˆë‹¤. +--------------------+--------------------------+---------------------+--------------------------------------------------------+ | 삽입MVCCID | ì´ì „ ë²„ì „ LSA | ì‚ì œ MVCCID | 스냅샷 테스트 ê²°ê³¼ | +====================+==========================+=====================+========================================================+ | Not visible | NULL | None ë˜ëŠ” | | ë²„ì „ì´ *ìµœì‹ * ì´ë©° 가시ì ì´ì§€ 않다. | | | | not visible | | ì´ì „ ë²„ì „ì´ ì—†ìœ¼ë¯€ë¡œ í–‰ì´ ë¬´ì‹œëœë‹¤. | | +--------------------------+---------------------+--------------------------------------------------------+ | | LSA | None ë˜ëŠ” | | ë²„ì „ì´ *ìµœì‹ * ì´ë©° 가시ì ì´ì§€ 않다. | | | | not visible | | ì´ì „ ë²„ì „ì´ ìžˆì–´ ìŠ¤ëƒ…ìƒ·ì€ í–‰ì˜ LSA를 확ì¸í•´ì•¼í•œë‹¤. | +--------------------+--------------------------+---------------------+--------------------------------------------------------+ | None or visible | LSA or NULL | None ë˜ëŠ” | | ë²„ì „ì´ ê°€ì‹œì ì´ë©° í–‰ì˜ ë°ì´í„°ê°€ 패치(fetch)ëœë‹¤. | | | | not visible | | ì´ì „ ë²„ì „ì´ ìžˆëŠ”ì§€ 여부는 중요하지 않다. | | | +---------------------+--------------------------------------------------------+ | | | Visible | | ë²„ì „ì´ ë„ˆë¬´ 오래ë˜ê³ , ì‚ì œë˜ì–´ 가시ì ì´ì§€ 않다. | | | | | | ì´ì „ ë²„ì „ì´ ìžˆëŠ”ì§€ 여부는 중요하지 않다. | +--------------------+--------------------------+---------------------+--------------------------------------------------------+ ë²„ì „ì´ ìµœì‹ ì´ì§€ë§Œ ë¡œê·¸ì— ì €ìž¥ëœ ì´ì „ ë²„ì „ì´ ìžˆëŠ” 경우 ì´ì „ ë²„ì „ì—ì„œë„ ë™ì¼í•œ í™•ì¸ ê³¼ì •ì´ ë°˜ë³µëœë‹¤. ë” ì´ìƒ ì´ì „ ë²„ì „ì´ ì—†ê±°ë‚˜(해당 트랜ìžì…˜ì— 대한 í–‰ ì²´ì¸ ì „ë¶€ê°€ ìµœì‹ ì¸ ê²½ìš°) 가시ì ì¸ ë²„ì „ì„ ë°œê²¬í•˜ë©´ 확ì¸ì´ 중지ëœë‹¤. ìŠ¤ëƒ…ìƒ·ì˜ ìž‘ë™ ì›ë¦¬ëŠ” 다ìŒê³¼ 같다(ì „ì²´ 트랜ìžì…˜ì—서 ë™ì¼í•œ ìŠ¤ëƒ…ìƒ·ì„ ìœ ì§€í•˜ê¸° 위해 **REPEATABLE READ** 격리 수준 사용). **ì˜ˆì œ 1: 새로운 í–‰ 삽입** +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | session 1 | session 2 | +===================================================================+===================================================================================+ | .. code-block:: sql | .. code-block:: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> set transaction isolation level REPEATABLE READ; | csql> set transaction isolation level REPEATABLE READ; | | | | | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> CREATE TABLE tbl(host_year integer, nation_code char(3)); | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | -- insert a row without committing | | | csql> INSERT INTO tbl VALUES (2008, 'AUS'); | | | | | | -- current transaction sees its own changes | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- this snapshot should not see uncommitted row | | | csql> SELECT * FROM tbl; | | | | | | There are no results. | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- even though inserter did commit, this snapshot still can't see the row | | | csql> SELECT * FROM tbl; | | | | | | There are no results. | | | | | | -- commit to start a new transaction with a new snapshot | | | csql> COMMIT WORK; | | | | | | -- the new snapshot should see committed row | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ **ì˜ˆì œ 2: í–‰ ì‚ì œ** +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | session 1 | session 2 | +===================================================================+===================================================================================+ | .. code-block:: sql | .. code-block:: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> set transaction isolation level REPEATABLE READ; | csql> set transaction isolation level REPEATABLE READ; | | | | | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> CREATE TABLE tbl(host_year integer, nation_code char(3)); | | | csql> INSERT INTO tbl VALUES (2008, 'AUS'); | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | -- delete the row without committing | | | csql> DELETE FROM tbl WHERE nation_code = 'AUS'; | | | | | | -- this transaction sees its own changes | | | csql> SELECT * FROM tbl; | | | | | | There are no results. | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- delete was not committed, so the row is visible to this snapshot | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- delete was committed, but the row is still visible to this snapshot | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | | | -- commit to start a new transaction with a new snapshot | | | csql> COMMIT WORK; | | | | | | -- the new snapshot can no longer see deleted row | | | csql> SELECT * FROM tbl; | | | | | | There are no results. | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ **ì˜ˆì œ 3: í–‰ ê°±ì‹ ** +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | session 1 | session 2 | +===================================================================+===================================================================================+ | .. code-block:: sql | .. code-block:: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> set transaction isolation level REPEATABLE READ; | csql> set transaction isolation level REPEATABLE READ; | | | | | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> CREATE TABLE tbl(host_year integer, nation_code char(3)); | | | csql> INSERT INTO tbl VALUES (2008, 'AUS'); | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | -- delete the row without committing | | | csql> UPDATE tbl SET host_year = 2012 WHERE nation_code = 'AUS';| | | | | | -- this transaction sees new version, host_year = 2012 | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2012 'AUS' | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- update was not committed, so this snapshot sees old version | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | .. code-block:: sql | | | | | | csql> COMMIT WORK; | | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ | | .. code-block:: sql | | | | | | -- update was committed, but this snapshot still sees old version | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | | | | -- commit to start a new transaction with a new snapshot | | | csql> COMMIT WORK; | | | | | | -- the new snapshot can see new version, host_year = 2012 | | | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | | | =================================== | | | 2012 'AUS' | | | | +-------------------------------------------------------------------+-----------------------------------------------------------------------------------+ **ì˜ˆì œ 4: 다양한 트랜ìžì…˜ì—서 ê°ê° 다른 ë²„ì „ì´ ë³´ìž„** +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ | session 1 | session 2 | session 3 | +===================================================================+========================================+========================================+ | .. code-block:: sql | .. code-block:: sql | .. code-block:: sql | | | | | | csql> ;autocommit off | csql> ;autocommit off | csql> ;autocommit off | | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | | csql> set transaction isolation level REPEATABLE READ; | csql> set transaction isolation | csql> set transaction isolation | | | level REPEATABLE READ; | level REPEATABLE READ; | | | | | | Isolation level set to: | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | REPEATABLE READ | | | | | +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ | .. code-block:: sql | | | | | | | | csql> CREATE TABLE tbl(host_year integer, nation_code char(3)); | | | | csql> INSERT INTO tbl VALUES (2008, 'AUS'); | | | | csql> COMMIT WORK; | | | | | | | +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ | .. code-block:: sql | .. code-block:: sql | | | | | | | -- update row | | | | csql> UPDATE tbl SET host_year = 2012 WHERE nation_code = 'AUS';| | | | | | | | csql> SELECT * FROM tbl; | csql> SELECT * FROM tbl; | | | | | | | host_year nation_code | host_year nation_code | | | =================================== | =================================== | | | 2012 'AUS' | 2008 'AUS' | | | | | | +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ | .. code-block:: sql | | | | | | | | csql> COMMIT WORK; | | | | | | | +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ | .. code-block:: sql | .. code-block:: sql | .. code-block:: sql | | | | | | csql> UPDATE tbl SET host_year = 2016 WHERE nation_code = 'AUS';| | | | | | | | csql> SELECT * FROM tbl; | csql> SELECT * FROM tbl; | csql> SELECT * FROM tbl; | | | | | | host_year nation_code | host_year nation_code | host_year nation_code | | =================================== | =================================== | =================================== | | 2016 'AUS' | 2008 'AUS' | 2012 'AUS' | | | | | +-------------------------------------------------------------------+----------------------------------------+----------------------------------------+ VACUUM ------ ê° ê°±ì‹ ì— ëŒ€í•´ 새 ë²„ì „ì„ ìƒì„±í•˜ê³ ì‚ì œ 시 ì´ì „ ë²„ì „ì„ ìœ ì§€í•˜ë©´ ë°ì´í„°ë² ì´ìФ í¬ê¸°ê°€ 무한으로 ì¦ê°€í•˜ì—¬ ë°ì´í„°ë² ì´ìŠ¤ì— í° ì´ìŠˆê°€ ë°œìƒí• 수 있다. ë”°ë¼ì„œ ì´ì „ ë°ì´í„°ë¥¼ ì œê±°í•˜ê³ ì ìœ ëœ ê³µê°„ì„ ìž¬ì‚¬ìš©í•˜ê¸° 위한 회수(Cleanup) ì‹œìŠ¤í…œì´ í•„ìš”í•˜ë‹¤. ê° í–‰ì˜ ë²„ì „ì€ ë‹¤ìŒê³¼ ê°™ì€ ë™ì¼í•œ 단계를 거친다. 1. 새로 삽입ë˜ì—ˆìœ¼ë‚˜ 커밋ë˜ì§€ 않으면, 삽입ìžë§Œ ë³¼ 수 ìžˆìŒ 2. 커밋ë˜ì—ˆìœ¼ë©´, ì´ì „ 트랜ìžì…˜ì—서는 ë³¼ 수 없으나 ì´í›„ 트랜ìžì…˜ì—서는 ë³¼ 수 ìžˆìŒ 3. ì‚ì œë˜ì—ˆìœ¼ë‚˜ 커밋ë˜ì§€ 않으면, 다른 트랜ìžì…˜ì—서는 ë³¼ 수 있으나 ì‚ì œìžëŠ” ë³¼ 수 ì—†ìŒ 4. 커밋ë˜ë©´, ì´ì „ 트랜ìžì…˜ì—서는 ë³¼ 수 있으나 ì´í›„ 트랜ìžì…˜ì—서는 ë³¼ 수 ì—†ìŒ 5. ëª¨ë“ í™œì„± 트랜ìžì…˜ì—서 ë³¼ 수 ì—†ìŒ 6. ë°ì´í„°ë² ì´ìФì—서 ì œê±°ë¨ íšŒìˆ˜ ì‹œìŠ¤í…œì˜ ì—í• ì€ 5~6단계ì—서 íšŒìˆ˜í• ë²„ì „ì„ íšë“하는 것ì´ë‹¤. CUBRIDì—서는 ì´ ì‹œìŠ¤í…œì„ **VACUUM** ì´ë¼ê³ 부른다. **VACUUM** ì‹œìŠ¤í…œì€ ì„¸ 가지 ì›ì¹™ì— ë”°ë¼ ê°œë°œë˜ì—ˆë‹¤. * **VACUUM** ì€ ì •í™•í•˜ê³ ì™„ì „í•´ì•¼ 한다. **VACUUM** ì€ ì¼ë¶€ 사용ìžê°€ ê³„ì† ë³¼ 수 있는 ë°ì´í„°ëŠ” ì œê±°í•˜ì§€ 않으며 ì´ì „ ë°ì´í„°ëŠ” í•˜ë‚˜ë„ ë†“ì¹˜ì§€ 않는다. * **VACUUM** ì€ ì‹ ì¤‘í•´ì•¼ 한다. 회수 프로세스는 ë°ì´í„°ë² ì´ìŠ¤ì˜ ë‚´ìš©ì„ ë³€ê²½í•˜ê¸° ë•Œë¬¸ì— ìˆ˜í–‰ ì¤‘ì¸ íŠ¸ëžœìžì…˜ì˜ ë™ìž‘ì— ê°„ì„ì„ ì¼ìœ¼í‚¬ 수 있지만 ì´ëŸ¬í•œ ê°€ëŠ¥ì„±ì„ ìµœì†Œí™”í•´ì•¼ 한다. * **VACUUM** ì€ ë¹ ë¥´ê³ íš¨ìœ¨ì ì´ì–´ì•¼ 한다. **VACUUM** ì´ ë„ˆë¬´ ëŠë¦¬ê±°ë‚˜ 지연ë˜ê¸° 시작하면 ë°ì´í„°ë² ì´ìФ ìƒíƒœê°€ ì•…í™”ë˜ì–´ ì „ì²´ ì„±ëŠ¥ì— ì˜í–¥ì„ ë¯¸ì¹ ìˆ˜ 있다. ì´ëŸ¬í•œ ì›ì¹™ì— ë”°ë¼ **VACUUM** êµ¬í˜„ì€ ë‹¤ìŒê³¼ ê°™ì€ ì´ìœ 로 기존 복구 ë¡œê¹…ì„ ì‚¬ìš©í–ˆë‹¤. * 복구 로깅ì—는 힙과 ì¸ë±ìФ 변경 사í•ì— ëŒ€í•œ 복구 ë°ì´í„°ì˜ 주소가 ìœ ì§€ëœë‹¤. 그래서 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 스캔하지 ì•Šê³ **VACUUM** ì´ ëŒ€ìƒìœ¼ë¡œ 바로 ì´ë™í• 수 있다. * 로그 ë°ì´í„°ì˜ 처리는 활성 Workerì˜ ìž‘ì—…ì— ê±°ì˜ ê°„ì„ì„ ì¼ìœ¼í‚¤ì§€ 않는다. MVCCID ì •ë³´ë¥¼ ë¡œê¹…ëœ ë°ì´í„°ì— ì¶”ê°€í•¨ìœ¼ë¡œì¨ **VACUUM** 요구 사í•ì— ë§žê²Œ 복구 ë¡œê¹…ì„ ì¡°ì •í–ˆë‹¤. 로그 엔트리를 ì²˜ë¦¬í• ì¤€ë¹„ê°€ ë˜ë©´ MVCCIDì— ë”°ë¼ **VACUUM** ì´ ê²°ì •ëœë‹¤. 활성 트랜ìžì…˜ì—서 ë³¼ 수 있는 MVCCID는 처리ë˜ì§€ 않는다. ì‹œê°„ì´ ì§€ë‚˜ë©´ ê° MVCCID를 사용한 변경 사í•ì„ ëª¨ë‘ ë³¼ 수 없게 ëœë‹¤. ê° íŠ¸ëžœìžì…˜ì€ 활성 ìƒíƒœë¡œ 간주ë˜ëŠ” 가장 ì˜¤ëž˜ëœ MVCCID를 ìœ ì§€í•œë‹¤. 활성으로 간주ë˜ëŠ” 가장 ì˜¤ëž˜ëœ MVCCID는 ëª¨ë“ íŠ¸ëžœìžì…˜ 중 가장 ì˜¤ëž˜ëœ MVCCIDì— ì˜í•´ ê²°ì •ëœë‹¤. ì´ ê°’ë³´ë‹¤ ì˜¤ëž˜ëœ ê²ƒì€ ë³´ì´ì§€ 않으므로 **VACUUM** ì´ íšŒìˆ˜í• ìˆ˜ 있다. VACUUM ë³‘ë ¬ 수행 ++++++++++++++++ **VACUUM** ì€ ì„¸ 번째 ì›ì¹™ì— ë”°ë¼ ë¹¨ë¼ì•¼ 하며 활성 Worker보다 뒤처지면 안 ëœë‹¤. 시스템 작업 부하가 ë§Žì€ ê²½ìš° í•˜ë‚˜ì˜ ìŠ¤ë ˆë“œì—서 ëª¨ë“ **VACUUM** ìž‘ì—…ì„ ì²˜ë¦¬í• ìˆ˜ 없기 ë•Œë¬¸ì— ë³‘ë ¬ 처리해야 한다. ë³‘ë ¬ 처리를 수행하기 위해 로그 ë°ì´í„°ë¥¼ ê³ ì • í¬ê¸° 블ë¡ìœ¼ë¡œ ë¶„í• í–ˆë‹¤. ì ì ˆí•œ 시기(ìµœì‹ ì˜ MVCCID를 vacuum 처리 í• ìˆ˜ 있ìŒ. ì´ëŠ” 블ë¡ì— 기ë¡ëœ ëª¨ë“ ìž‘ì—…ì„ vacuum í• ìˆ˜ 있ìŒì„ ì˜ë¯¸í•¨)ê°€ ë˜ë©´ ê° ë¸”ë¡ë§ˆë‹¤ í•˜ë‚˜ì˜ vacuum ìž‘ì—…ì„ ìƒì„±í•œë‹¤. vacuum ìž‘ì—…ì€ ë¡œê·¸ 블ë¡ì— 있는 ê´€ë ¨ 로그 í•ëª©ì„ ê¸°ë°˜ìœ¼ë¡œ ë°ì´í„° ê³µê°„ì„ íšŒìˆ˜í•˜ëŠ” **VACUUM Worker** ë“¤ì— ì˜í•´ ì„ íƒëœë‹¤. 로그 블ë¡ì˜ ì¶”ì ë° vacuum ìž‘ì—…ì˜ ìƒì„±ì€ **VACUUM Master** ê°€ 수행한다. VACUUM ë°ì´í„° +++++++++++++ 로그 블ë¡ì—서 ìˆ˜ì§‘ëœ ë°ì´í„°ëŠ” vacuum ë°ì´í„° 파ì¼ì— ì €ìž¥ëœë‹¤. ìƒì„±ëœ vacuum ìž‘ì—…ì€ ë‚˜ì¤‘ì— ìˆ˜í–‰ë˜ë¯€ë¡œ vacuum ìž‘ì—…ì„ ìˆ˜í–‰í• ìˆ˜ ìžˆì„ ë•Œê¹Œì§€ ë°ì´í„°ê°€ ì €ìž¥ë˜ì–´ì•¼ 하며 서버가 ë¹„ì •ìƒ ì¢…ë£Œí•˜ëŠ” 경우ì—ë„ ìœ ì§€ë˜ì–´ì•¼ 한다. vacuum ìž‘ì—…ì€ ë¹ ì§ì—†ì´ 수행ë˜ì–´ì•¼ 한다. ì„œë²„ì˜ ë¹„ì •ìƒ ì¢…ë£Œë¡œ ì¸í•´ ì „í˜€ 수행ë˜ì§€ 않는 경우를 피하기 위해 ìž‘ì—…ì´ ë‘ ë²ˆ 수행ë˜ê¸°ë„ 한다. ìž‘ì—…ì´ ì„±ê³µì 으로 ìˆ˜í–‰ëœ í›„ ì²˜ë¦¬ëœ ë¡œê·¸ 블ë¡ì˜ ìˆ˜ì§‘ëœ ë°ì´í„°ê°€ ì œê±°ëœë‹¤. ìˆ˜ì§‘ëœ ë¡œê·¸ ë¸”ë¡ ë°ì´í„°ëŠ” vacuum ë°ì´í„°ì— 바로 추가ë˜ì§€ 않는다. vacuum 시스템ì—서 작업 ì¤‘ì¸ ìŠ¤ë ˆë“œ(로그 ë¸”ë¡ ë° ìˆ˜ì§‘ ë°ì´í„° ìƒì„±)ë“¤ì˜ ê°„ì„ì„ í”¼í•˜ê¸° 위해 래치-프리(latch-free) 버í¼ê°€ 사용ëœë‹¤. **VACUUM Master** ê°€ 주기ì 으로 활성화ë˜ì–´ 버í¼ì— 있는 ëª¨ë“ ë‚´ìš©ì„ vacuum ë°ì´í„°ë¡œ ì €ìž¥í•˜ê³ , ì´ë¯¸ ì²˜ë¦¬ëœ ë°ì´í„°ë¥¼ ì œê±°í•œ 후 새로운 작업(사용 가능한 경우)ì„ ìƒì„±í•œë‹¤. VACUUM 작업 +++++++++++ VACUUM 작업 실행 단계는 다ìŒê³¼ 같다. 1. **로그 프리패치** : vacuum Master ë˜ëŠ” Workerê°€ 작업으로 ì²˜ë¦¬í• ë¡œê·¸ 페ì´ì§€ë¥¼ 프리패치한다. 2. **ê° ë¡œê·¸ ë ˆì½”ë“œì— ëŒ€í•´ ë‹¤ìŒ ìž‘ì—…ì„ ë°˜ë³µí•œë‹¤**. 1. 로그 ë ˆì½”ë“œë¥¼ **ì½ëŠ”ë‹¤**. 2. **ì‚ì œëœ íŒŒì¼ì„ 확ì¸í•œë‹¤.** : 로그 ë ˆì½”ë“œê°€ ì‚ì œëœ íŒŒì¼ì„ 가리키면 ë‹¤ìŒ ë¡œê·¸ ë ˆì½”ë“œë¡œ ì´ë™í•œë‹¤. 3. **ì¸ë±ìФ vacuumì„ ìˆ˜í–‰í•˜ê³ íž™ OID를 수집한다.** * 로그 ë ˆì½”ë“œê°€ ì¸ë±ìŠ¤ì— ì†í•´ 있는 경우 바로 vacuumì„ ìˆ˜í–‰í•œë‹¤. * 로그 ë ˆì½”ë“œê°€ íž™ì— ì†í•´ 있는 경우 ë‚˜ì¤‘ì— vacuumì„ ìˆ˜í–‰í• OID를 수집한다. 3. ìˆ˜ì§‘ëœ OIDì— ë”°ë¼ **íž™ vacuumì„ ìˆ˜í–‰** 한다. 4. **ìž‘ì—…ì„ ì™„ë£Œí•œë‹¤.** vacuum ë°ì´í„°ì—서 ìž‘ì—…ì„ ì™„ë£Œë¨ìœ¼ë¡œ 표시한다. 로그 페ì´ì§€ ì½ê¸°ë¥¼ 쉽게 í•˜ê³ vacuum ìˆ˜í–‰ì„ ìµœì 화하기 위해 여러 가지 ë°©ë²•ì´ ìˆ˜í–‰ë˜ì—ˆë‹¤. ì‚ì œëœ íŒŒì¼ ì¶”ì ++++++++++++++++ 트랜ìžì…˜ì—서 í…Œì´ë¸” ë˜ëŠ” ì¸ë±ìŠ¤ê°€ ì‚ì œë˜ë©´ ì¼ë°˜ì 으로 해당 í…Œì´ë¸”ì„ ìž ê¶ˆ 다른 트랜ìžì…˜ì´ 액세스하지 못하ë„ë¡ ì°¨ë‹¨í•œë‹¤. 그러나 활성 트랜ìžì…˜ê³¼ 달리, **VACUUM** worker는 활성 트랜ìžì…˜ì— 대한 ê°„ì„ì„ ìµœì†Œí™”í•´ì•¼ í•˜ê³ , íšŒìˆ˜í• ë°ì´í„°ê°€ 있는 경우 **VACUUM** ì‹œìŠ¤í…œì€ ì ˆëŒ€ë¡œ 중지ë˜ë©´ 안ë˜ë¯€ë¡œ ìž ê¸ˆ ì‹œìŠ¤í…œì„ ì‚¬ìš©í•˜ì§€ 않는다. ë˜í•œ, **VACUUM** ì€ íšŒìˆ˜ê°€ 필요한 ë°ì´í„°ë¥¼ 건너뛸 수 없다. ì´ì— 따른 ë‘ ê°€ì§€ 결과는 다ìŒê³¼ 같다. 1. **VACUUM** ì€ ì‚ì œìž(dropper)ê°€ ì»¤ë°‹í• ë•Œê¹Œì§€ ì‚ì œëœ í…Œì´ë¸” ë˜ëŠ” ì‚ì œëœ ì¸ë±ìŠ¤ì— ì†í•œ 파ì¼ì„ ì‚ì œí•˜ì§€ 않는다. 트랜ìžì…˜ì—서 í…Œì´ë¸”ì„ ì‚ì œí•œ 경우ì—ë„ í•´ë‹¹ 파ì¼ì´ 즉시 ì‚ì œë˜ì§€ ì•Šê³ ê³„ì† ì•¡ì„¸ìŠ¤ í• ìˆ˜ 있다. 실질ì ì¸ ì‚ì œëŠ” 커밋한 ì´í›„로 연기ëœë‹¤. 2. ì‹¤ì œ 파ì¼ì´ ì‚ì œë˜ê¸° ì „ì— **VACUUM** ì‹œìŠ¤í…œì— ì•Œë ¤ì•¼ 한다. ì‚ì œìž(dropper)ê°€ **VACUUM** ì‹œìŠ¤í…œì— ì•Œë¦¼ì„ ë³´ë‚´ê³ í™•ì¸ì„ 기다린다. **VACUUM** ìž‘ì—…ì˜ ë°˜ë³µ 주기는 매우 ì§§ê³ ìƒˆë¡ê²Œ ì‚ì œëœ íŒŒì¼ì´ 있는지 ìžì£¼ 확ì¸í•˜ë¯€ë¡œ ì‚ì œìž(dropper)ê°€ 오랫ë™ì•ˆ 기다리지 ì•Šì•„ë„ ëœë‹¤. 파ì¼ì´ ì‚ì œëœ í›„ì—는 **VACUUM** ì€ í•´ë‹¹ 파ì¼ì— ì†í•œ ëª¨ë“ ë¡œê·¸ 엔트리를 무시한다. **VACUUM** ì—서 ì œê±°í•´ë„ ëœë‹¤ê³ ê²°ì •í• ë•Œê¹Œì§€(ì•„ì§ vacuumë˜ì§€ ì•Šì€ ê°€ìž¥ ì˜¤ëž˜ëœ MVCCIDì— ë”°ë¼ ê²°ì •ë¨) ì‚ì œ 시ì ì´ í‘œì‹œëœ MVCCID와 함께 íŒŒì¼ ì‹ë³„ìžê°€ ì˜êµ¬ 파ì¼ì— ì €ìž¥ëœë‹¤. .. _lock-protocol: ìž ê¸ˆ í”„ë¡œí† ì½œ ============= 2단계 ìž ê¸ˆ í”„ë¡œí† ì½œì—서는 ë™ì‹œì— ì—°ì‚° ì¶©ëŒì´ ë°œìƒí•˜ì§€ 않ë„ë¡ íŠ¸ëžœìžì…˜ì´ ê°ì²´ë¥¼ ì½ê¸° ì „ì— ê³µìœ ìž ê¸ˆì„ íšë“í•˜ê³ , ê°±ì‹ í•˜ê¸° ì „ì— ë°°íƒ€ ìž ê¸ˆì„ íšë“한다. 현재 CUBRIDì—서 ì‚¬ìš©í•˜ê³ ìžˆëŠ” MVCC ìž ê¸ˆ í”„ë¡œí† ì½œì€ í–‰ì„ ì½ê¸° ì „ì— ê³µìœ ìž ê¸ˆì´ í•„ìš”í•˜ì§€ 않다. 그러나 í…Œì´ë¸” ê°ì²´ì— ì˜ë„ ê³µìœ ìž ê¸ˆì€ í•´ë‹¹ í–‰ì„ ì½ì„ 때 ê³„ì† ì‚¬ìš©ëœë‹¤. 트랜ìžì…˜ *T1* ì— ìž ê¸ˆì´ í•„ìš”í•œ 경우 CUBRIDì—서 ìš”ì²ëœ ìž ê¸ˆì´ ê¸°ì¡´ ìž ê¸ˆê³¼ ì¶©ëŒí•˜ëŠ”ì§€ 확ì¸í•œë‹¤. ì¶©ëŒì´ ë°œìƒí•˜ë©´ 트랜ìžì…˜ *T1* ì€ ëŒ€ê¸° ìƒíƒœê°€ ë˜ê³ ìž ê¸ˆì´ ì§€ì—°ëœë‹¤. 다른 트랜ìžì…˜ *T2* ê°€ ìž ê¸ˆì„ í•´ì œí•˜ë©´ 트랜ìžì…˜ *T1* ì´ ë‹¤ì‹œ 시작ë˜ì–´ ìž ê¸ˆì„ íšë“한다. ìž ê¸ˆì´ í•´ì œë˜ë©´ 해당 트랜ìžì…˜ì—서 새로운 ìž ê¸ˆì„ íšë“í• í•„ìš”ê°€ 없다. ìž ê¸ˆì˜ ë‹¨ìœ„ ----------- CUBRID는 ìž ê¸ˆì˜ ê°œìˆ˜ë¥¼ 줄ì´ê¸° 위해서 단위 ìž ê¸ˆ(granularity locking) í”„ë¡œí† ì½œì„ ì‚¬ìš©í•œë‹¤. 단위 ìž ê¸ˆ í”„ë¡œí† ì½œì—서는 ìž ê¸ˆ ë‹¨ìœ„ì˜ í¬ê¸°ì— ë”°ë¼ ê³„ì¸µìœ¼ë¡œ 모ë¸í™”ë˜ë©°, í–‰ ìž ê¸ˆ(row lock), í…Œì´ë¸” ìž ê¸ˆ(table lock), ë°ì´í„°ë² ì´ìФ ìž ê¸ˆ(database lock)ì´ ìžˆë‹¤. ì´ë•Œ, 단위가 í° ìž ê¸ˆì€ ìž‘ì€ ë‹¨ìœ„ì˜ ìž ê¸ˆì„ ë‚´í¬í•œë‹¤. ìž ê¸ˆì„ ì„¤ì •í•˜ê³ í•´ì œí•˜ëŠ” ê³¼ì •ì—서 ë°œìƒí•˜ëŠ” 성능 ì†ì‹¤ì„ ìž ê¸ˆ 비용(overhead)ì´ë¼ê³ 하는ë°, í° ë‹¨ìœ„ë³´ë‹¤ ìž‘ì€ ë‹¨ìœ„ì˜ ìž ê¸ˆì„ ìˆ˜í–‰í• ë•Œ ì´ëŸ¬í•œ ìž ê¸ˆ ë¹„ìš©ì´ ë†’ì•„ì§€ê³ ëŒ€ì‹ íŠ¸ëžœìžì…˜ ë™ì‹œì„±ì€ í–¥ìƒëœë‹¤. ë”°ë¼ì„œ, CUBRID는 ìž ê¸ˆ 비용과 트랜ìžì…˜ ë™ì‹œì„±ì„ ê³ ë ¤í•˜ì—¬ ìž ê¸ˆ 단위를 ê²°ì •í•œë‹¤. 예를 들어, 한 트랜ìžì…˜ì´ í…Œì´ë¸”ì˜ ëª¨ë“ í–‰ë“¤ì„ ì¡°íšŒí•˜ëŠ” 경우 í–‰ 단위로 ìž ê¸ˆì„ ì„¤ì •/í•´ì œí•˜ëŠ” ë¹„ìš©ì´ ë„ˆë¬´ 높으므로 ì°¨ë¼ë¦¬ 해당 í…Œì´ë¸”ì— ìž ê¸ˆì„ ì„¤ì •í•œë‹¤. ì´ì²˜ëŸ¼ í…Œì´ë¸”ì— ìž ê¸ˆì´ ì„¤ì •ë˜ë©´ 트랜ìžì…˜ ë™ì‹œì„±ì´ ì €í•˜ë˜ë¯€ë¡œ, ë™ì‹œì„±ì„ ë³´ìž¥í•˜ë ¤ë©´ í’€ 스캔(full scan)ì´ ë°œìƒí•˜ì§€ 않ë„ë¡ ì ì ˆí•œ ì¸ë±ìŠ¤ë¥¼ 사용해야 í• ê²ƒì´ë‹¤. ì´ì™€ ê°™ì€ ìž ê¸ˆ 관리를 위해 CUBRID는 ìž ê¸ˆ ì—ìŠ¤ì»¬ë ˆì´ì…˜(lock escalation) ê¸°ë²•ì„ ì‚¬ìš©í•˜ì—¬ ì„¤ì • 가능한 단위 ìž ê¸ˆì˜ ìˆ˜ë¥¼ ì œí•œí•œë‹¤. 예를 들어, 한 트랜ìžì…˜ì´ í–‰ 단위ì—서 íŠ¹ì • 개수 ì´ìƒì˜ ìž ê¸ˆì„ ê°€ì§€ê³ ìžˆìœ¼ë©´ ì‹œìŠ¤í…œì€ ê³„ì¸µì 으로 ìƒìœ„ ë‹¨ìœ„ì¸ í…Œì´ë¸”ì— ëŒ€í•´ ìž ê¸ˆì„ ìš”ì²í•˜ê¸° 시작한다. 단, ìƒìœ„ 단위로 ìž ê¸ˆ ì—ìŠ¤ì»¬ë ˆì´ì…˜ì„ 수행하기 위해서는 ì–´ë–¤ 트랜ìžì…˜ë„ ìƒìœ„ 단위 ê°ì²´ì— 대한 ìž ê¸ˆì„ ê°€ì§€ê³ ìžˆì§€ 않아야 한다. 그래야만 ìž ê¸ˆ ë³€í™˜ì— ë”°ë¥¸ êµì°© ìƒíƒœ(deadlock)를 ì˜ˆë°©í• ìˆ˜ 있다. ì´ë•Œ, ìž‘ì€ ë‹¨ìœ„ì—서 허용하는 ìž ê¸ˆ 개수는 시스템 파ë¼ë¯¸í„° **lock_escalation** ì„ í†µí•´ ì„¤ì •í• ìˆ˜ 있다. .. _lock-mode: ìž ê¸ˆ ëª¨ë“œì˜ ì¢…ë¥˜ì™€ 호환성 ------------------------- CUBRID는 트랜ìžì…˜ì´ ìˆ˜í–‰í•˜ê³ ìž í•˜ëŠ” ì—°ì‚°ì˜ ì¢…ë¥˜ì— ë”°ë¼ íšë“í•˜ê³ ìž í•˜ëŠ” ìž ê¸ˆ 모드를 ê²°ì •í•˜ë©°, 다른 트랜ìžì…˜ì— ì˜í•´ ì´ë¯¸ ì„ ì ëœ ìž ê¸ˆ ëª¨ë“œì˜ ì¢…ë¥˜ì— ë”°ë¼ ìž ê¸ˆ ê³µìœ ì—¬ë¶€ë¥¼ ê²°ì •í•œë‹¤. ì´ì™€ ê°™ì€ ìž ê¸ˆì— ëŒ€í•œ ê²°ì •ì€ ì‹œìŠ¤í…œì´ ìžë™ìœ¼ë¡œ 수행하며, 사용ìžì— ì˜í•œ ìˆ˜ë™ ì§€ì •ì€ í—ˆìš©ë˜ì§€ 않는다. CUBRIDì˜ ìž ê¸ˆ ì •ë³´ë¥¼ 확ì¸í•˜ê¸° 위해서는 **cubrid lockdb** *db_name* ëª…ë ¹ì–´ë¥¼ 사용하며, ìžì„¸í•œ ë‚´ìš©ì€ :ref:`lockdb` ì„ ì°¸ê³ í•œë‹¤. * **ê³µìœ ìž ê¸ˆ(shared lock, S_LOCK, MVCC í”„ë¡œí† ì½œì—서는 ë” ì´ìƒ 사용 안 함)** ê°ì²´ì— 대해 ì½ê¸° ì—°ì‚°ì„ ìˆ˜í–‰í•˜ê¸° ì „ì— íšë“하며, 여러 트랜ìžì…˜ì´ ë™ì¼ ê°ì²´ì— 대해 íšë“í• ìˆ˜ 있는 ìž ê¸ˆì´ë‹¤. 트랜ìžì…˜ T1ì´ íŠ¹ì • ê°ì²´ì— 대해 ì½ê¸° ì—°ì‚°ì„ ìˆ˜í–‰í•˜ê¸° ì „ì— ê³µìœ ìž ê¸ˆì„ ë¨¼ì € íšë“한다. ì´ë•Œ, 트랜ìžì…˜ *T2* , *T3* ì€ ë™ì‹œì— ê·¸ ê°ì²´ì— 대해 ì½ê¸° ì—°ì‚°ì„ ìˆ˜í–‰í• ìˆ˜ 있으나 ê°±ì‹ ì—°ì‚°ì„ ìˆ˜í–‰í• ìˆ˜ 없다. .. note:: * CUBRID 10.0ì—서는 MVCC를 사용하므로 ê³µìœ ìž ê¸ˆì€ ê±°ì˜ ì‚¬ìš©ë˜ì§€ 않는다. 현재는 ë‚´ë¶€ ë°ì´í„°ë² ì´ìФ ì—°ì‚°ì—서 í–‰ ë˜ëŠ” ì¸ë±ìФ 키가 ìˆ˜ì •ë˜ëŠ” ê²ƒì„ ë°©ì§€í•˜ëŠ” ë° ì£¼ë¡œ 사용ëœë‹¤. * **배타 ìž ê¸ˆ(Exclusive lock, X_LOCK)** ê°ì²´ì— 대해 ê°±ì‹ ì—°ì‚°ì„ ìˆ˜í–‰í•˜ê¸° ì „ì— íšë“하며, í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ë§Œ íšë“í• ìˆ˜ 있는 ìž ê¸ˆì´ë‹¤. 트랜ìžì…˜ *T1* ì´ íŠ¹ì • ê°ì²´ Xì— ëŒ€í•´ ê°±ì‹ ì—°ì‚°ì„ ìˆ˜í–‰í•˜ê¸° ì „ì— ë°°íƒ€ ìž ê¸ˆì„ ë¨¼ì € íšë“í•˜ê³ , ê°±ì‹ ì—°ì‚°ì„ ì™„ë£Œí•˜ë”ë¼ë„ 트랜ìžì…˜ *T1* ì´ ì»¤ë°‹ë 때까지 배타 ìž ê¸ˆì„ í•´ì œí•˜ì§€ 않는다. ë”°ë¼ì„œ, 트랜ìžì…˜ *T2*, *T3* ì€ íŠ¸ëžœìžì…˜ *T1* ì´ ë°°íƒ€ ìž ê¸ˆì„ í•´ì œí•˜ê¸° ì „ê¹Œì§€ëŠ” Xì— ëŒ€í•œ ì½ê¸° ì—°ì‚°ë„ ìˆ˜í–‰í• ìˆ˜ 없다. * **ì˜ë„ ìž ê¸ˆ(ë‚´ìž¬ëœ ìž ê¸ˆ, Intent lock)** íŠ¹ì • ë‹¨ìœ„ì˜ ê°ì²´ì— 걸리는 ìž ê¸ˆì„ ë³´í˜¸í•˜ê¸° 위하여 ì´ ê°ì²´ë³´ë‹¤ ìƒìœ„ ë‹¨ìœ„ì˜ ê°ì²´ì— 내재ì 으로 ì„¤ì •í•˜ëŠ” ìž ê¸ˆì„ ì˜ë¯¸í•œë‹¤. 예를 들어, íŠ¹ì • í–‰ì— ê³µìœ ìž ê¸ˆì´ ìš”ì²ë˜ë©´ ì´ë³´ë‹¤ 계층ì 으로 ìƒìœ„ì— ìžˆëŠ” í…Œì´ë¸”ì—ë„ ì˜ë„ ê³µìœ ìž ê¸ˆì„ í•¨ê»˜ ì„¤ì •í•˜ì—¬ 다른 트랜ìžì…˜ì— ì˜í•´ í…Œì´ë¸”ì´ ìž ê¸ˆë˜ëŠ” ê²ƒì„ ì˜ˆë°©í•œë‹¤. ë”°ë¼ì„œ, ì˜ë„ ìž ê¸ˆì€ ê³„ì¸µì 으로 가장 ë‚®ì€ ë‹¨ìœ„ì¸ í–‰ì— ëŒ€í•´ì„œëŠ” ì„¤ì •ë˜ì§€ 않으며, ì´ë³´ë‹¤ ë†’ì€ ë‹¨ìœ„ì˜ ê°ì²´ì— 대해서만 ì„¤ì •ëœë‹¤. ì˜ë„ ìž ê¸ˆì˜ ì¢…ë¥˜ëŠ” 다ìŒê³¼ 같다. * **ì˜ë„ ê³µìœ ìž ê¸ˆ(Intent shared lock, IS_LOCK)** íŠ¹ì • í–‰ì— ê³µìœ ìž ê¸ˆì´ ì„¤ì •ë¨ì— ë”°ë¼ ìƒìœ„ ê°ì²´ì¸ í…Œì´ë¸”ì— ì˜ë„ ê³µìœ ìž ê¸ˆì´ ì„¤ì •ë˜ë©´, 다른 트랜ìžì…˜ì€ ì¹¼ëŸ¼ì„ ì¶”ê°€í•˜ê±°ë‚˜ í…Œì´ë¸” ì´ë¦„ì„ ë³€ê²½í•˜ëŠ” ë“±ì˜ í…Œì´ë¸” 스키마를 ë³€ê²½í• ìˆ˜ ì—†ê³ , ëª¨ë“ í–‰ì„ ê°±ì‹ í•˜ëŠ” ìž‘ì—…ì„ ìˆ˜í–‰í• ìˆ˜ 없다. 그러나 ì¼ë¶€ í–‰ì„ ê°±ì‹ í•˜ëŠ” 작업ì´ë‚˜, ëª¨ë“ í–‰ì„ ì¡°íšŒí•˜ëŠ” ìž‘ì—…ì€ í—ˆìš©ëœë‹¤. * **ì˜ë„ 배타 ìž ê¸ˆ(Intent exclusive lock, IX_LOCK)** íŠ¹ì • í–‰ì— ë°°íƒ€ ìž ê¸ˆì´ ì„¤ì •ë¨ì— ë”°ë¼ ìƒìœ„ ê°ì²´ì¸ í…Œì´ë¸”ì— ì˜ë„ 배타 ìž ê¸ˆì´ ì„¤ì •ë˜ë©´, 다른 트랜ìžì…˜ì€ í…Œì´ë¸” 스키마를 ë³€ê²½í• ìˆ˜ ì—†ê³ , ëª¨ë“ í–‰ì„ ê°±ì‹ í•˜ëŠ” ìž‘ì—…ì€ ë¬¼ë¡ , ëª¨ë“ í–‰ì„ ì¡°íšŒí•˜ëŠ” ìž‘ì—…ì€ ìˆ˜í–‰í• ìˆ˜ 없다. 그러나, ì¼ë¶€ í–‰ì„ ê°±ì‹ í•˜ëŠ” ìž‘ì—…ì€ í—ˆìš©ëœë‹¤. * **ê³µìœ ì˜ë„ 배타 ìž ê¸ˆ(shared with intent exclusive lock, SIX_LOCK)** 계층ì 으로 ë” ë‚®ì€ ëª¨ë“ ê°ì²´ì— ì„¤ì •ëœ ê³µìœ ìž ê¸ˆì„ ë³´í˜¸í•˜ê³ , 계층ì 으로 ë” ë‚®ì€ ì¼ë¶€ ê°ì²´ì— 대한 ì˜ë„ 배타 ìž ê¸ˆì„ ë³´í˜¸í•˜ê¸° 위하여 ìƒìœ„ ê°ì²´ì— 내재ì 으로 ì„¤ì •ë˜ëŠ” ìž ê¸ˆì´ë‹¤. í…Œì´ë¸”ì— ê³µìœ ì˜ë„ 배타 ìž ê¸ˆì´ ì„¤ì •ë˜ë©´, 다른 트랜ìžì…˜ì€ í…Œì´ë¸” 스키마를 ë³€ê²½í• ìˆ˜ ì—†ê³ , ëª¨ë“ í–‰/ì¼ë¶€ í–‰ì„ ê°±ì‹ í• ìˆ˜ 없으며, ëª¨ë“ í–‰ì„ ì¡°íšŒí• ìˆ˜ 없다. 그러나, ì¼ë¶€ í–‰ì„ ì¡°íšŒí•˜ëŠ” ìž‘ì—…ì€ í—ˆìš©ëœë‹¤. * **스키마 ìž ê¸ˆ** DDL ìž‘ì—…ì„ ìˆ˜í–‰í• ë•Œ 스키마 ìž ê¸ˆì„ íšë“한다. * **스키마 ì•ˆì • ìž ê¸ˆ(schema stability lock, SCH_S_LOCK)** ì§ˆì˜ ì»´íŒŒì¼ì„ 수행하는 ë™ì•ˆ íšë“ë˜ë©° 질ì˜ì— í¬í•¨ëœ 스키마가 다른 트랜ìžì…˜ì— ì˜í•´ ìˆ˜ì •ë˜ì§€ 않ìŒì„ 보장한다. * **스키마 ìˆ˜ì • ìž ê¸ˆ(schema modification lock, SCH_M_LOCK)** DDL(**ALTER**/**CREATE**/**DROP**)ì„ ì‹¤í–‰í•˜ëŠ” ë™ì•ˆ íšë“ë˜ë©° 다른 트랜ìžì…˜ì´ ìˆ˜ì •ëœ ìŠ¤í‚¤ë§ˆì— ì ‘ê·¼í•˜ëŠ” ê²ƒì„ ë°©ì§€í•œë‹¤. **ALTER**, **CREATE INDEX** 등 ì¼ë¶€ DDL ì—°ì‚°ì€ **SCH_M_LOCK** ì„ ì§ì ‘ íšë“하지 않는다. 예를 들어 í•„í„°ë§ëœ ì¸ë±ìŠ¤ë¥¼ ìƒì„±í• 때, CUBRID는 í•„í„°ë§ í‘œí˜„ì‹ì— 대한 타입 검사를 수행한다. ì´ ê¸°ê°„ ë™ì•ˆ, ëŒ€ìƒ í…Œì´ë¸”ì— ìœ ì§€ë˜ëŠ” ìž ê¸ˆì€ ë‹¤ë¥¸ 타입 검사 ì—°ì‚°ì˜ ê²½ìš°ì²˜ëŸ¼ **SCH_S_LOCK** ì´ë‹¤. 그런 ë‹¤ìŒ ìž ê¸ˆì´ **SIX_LOCK** 으로 ì—…ê·¸ë ˆì´ë“œë˜ê³ (다른 트랜ìžì…˜ì´ ëŒ€ìƒ í…Œì´ë¸” í–‰ì„ ìˆ˜ì •í• ìˆ˜ 없지만 ê³„ì† ì½ì„ 수는 있ìŒ), 마지막으로 í…Œì´ë¸” 스키마를 변경하기 위해 **SCH_M_LOCK** ì´ ìš”ì²ëœë‹¤. ì´ëŸ¬í•œ ë°©ì‹ì€ DDL ì—°ì‚°ì´ ì»´íŒŒì¼ë˜ê³ 수행ë˜ëŠ” ë™ì•ˆ 다른 트랜ìžì…˜ì´ ì—°ì‚°ì„ ìˆ˜í–‰í•˜ëŠ” ê²ƒì„ í—ˆìš©í•˜ì—¬, ë™ì‹œì„±ì„ ë†’ì¼ ìˆ˜ 있다는 ì´ì ì´ ìžˆë‹¤. 하지만 ì´ ë°©ì‹ì€ ê°™ì€ í…Œì´ë¸”ì— ë™ì‹œì— DDL ì—°ì‚°ì„ ìˆ˜í–‰í• ë•Œ êµì°© ìƒíƒœë¥¼ íšŒí”¼í• ìˆ˜ 없다는 단ì ë˜í•œ 존재한다. ì¸ë±ìŠ¤ë¥¼ 로딩함으로 ì¸í•œ êµì°© ìƒíƒœì˜ 예는 다ìŒê³¼ 같다. 그러나 ì´ ë°©ì‹ì€ ê°™ì€ í…Œì´ë¸”ì— ë™ì‹œì— DDL ì—°ì‚°ì„ ìˆ˜í–‰í• ë•Œ êµì°© ìƒíƒœë¥¼ íšŒí”¼í• ìˆ˜ 없다는 단ì ë˜í•œ 존재한다. ì¸ë±ìФ 로딩으로 ì¸í•œ êµì°© ìƒíƒœì˜ 예는 다ìŒê³¼ 같다. +---------------------------------------------------------------+---------------------------------------------------------------+ | T1 | T2 | +===============================================================+===============================================================+ | .. code-block:: sql | .. code-block :: sql | | | | | CREATE INDEX i_t_i on t(i) WHERE i > 0; | CREATE INDEX i_t_j on t(j) WHERE j > 0; | +---------------------------------------------------------------+---------------------------------------------------------------+ | "i > 0" ê²½ìš°ì˜ íƒ€ìž… ê²€ì‚¬ì¤‘ì— SCH_S_LOCK. | | +---------------------------------------------------------------+---------------------------------------------------------------+ | | "j > 0" case."j > 0" 타입 ê²€ì‚¬ì¤‘ì— SCH_S_LOCK | +---------------------------------------------------------------+---------------------------------------------------------------+ | ì¸ë±ìФ 로딩 ì¤‘ì— SIX_LOCK. | | +---------------------------------------------------------------+---------------------------------------------------------------+ | | SIX_LOCKì„ ìš”êµ¬í•˜ë‚˜ T1ì´ SIX_LOCKì˜ ë°˜í™˜ì„ ëŒ€ê¸° | +---------------------------------------------------------------+---------------------------------------------------------------+ | SCH_M_LOCKì„ ìš”êµ¬í•˜ë‚˜ T2ê°€ SCH_S_LOCKì˜ ë°˜í™˜ì„ ëŒ€ê¸° | | +---------------------------------------------------------------+---------------------------------------------------------------+ * **특수 ìž ê¸ˆ** **CUBRID 10.2** 시스템 ë‚´ë¶€ì 으로 특수한 오í¼ë ˆì´ì…˜ì—서 사용하는 새로운 ìœ í˜•ì˜ ìž ê¸ˆì„ ì†Œê°œí•œë‹¤. * **ëŒ€ëŸ‰ê°±ì‹ ìž ê¸ˆ(Bulk update lock, BU_LOCK)** ì´ ìž ê¸ˆì€ ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€ëŸ‰ì˜ ë°ì´íƒ€ë¥¼ 삽입하는 ê²½ìš°ì— ì‚¬ìš©í•˜ë„ë¡ ì„¤ê³„ë˜ì—ˆë‹¤. **CUBRID 10.2** 를 기준으로, ì´ ìž ê¸ˆì€ í…Œì´ë¸”ì— í–‰ì„ load하는 ë™ì•ˆ :ref:`loaddb` ê³¼ì •ì—서 배타ì 으로 사용ëœë‹¤. **BU_LOCK** ì€ ìžê¸° ìžì‹ ê³¼ **SCH_S_LOCK** ì— í˜¸í™˜ëœë‹¤. ê²°ê³¼ì 으로 ì´ ìž ê¸ˆì€ ë‹¤ë¥¸ ì–´ë–¤ **SELECT/DML/DDL** êµ¬ë¬¸ë„ ë™ì¼í•œ í…Œì´ë¸”ì— ì ‘ê·¼í•˜ì§€ 못한다는 ê²ƒì„ ë³´ìž¥í•œë‹¤. 그러나 둘 ì´ìƒì˜ **loaddb** ê°€ í•˜ë‚˜ì˜ í…Œì´ë¸”ì— í–‰ì„ loadí• ìˆ˜ëŠ” 있다. **BU_LOCK** ìž ê¸ˆ ë³´ìœ ìžëŠ” í–‰ ìž ê¸ˆì„ ìš”êµ¬í•˜ì§„ 않는다. .. note:: ìž ê¸ˆì— ëŒ€í•´ 요약하면 다ìŒê³¼ 같다. * ìž ê¸ˆ ëŒ€ìƒ ê°ì²´ì— 대해 í–‰(ì¸ìŠ¤í„´ìŠ¤)ê³¼ 스키마(í´ëž˜ìФ)ê°€ 있다. ì‚¬ìš©ëœ ê°ì²´ 종류를 기준으로 ìž ê¸ˆì„ ë‚˜ëˆ„ë©´ 다ìŒê³¼ 같다. * í–‰ ìž ê¸ˆ: **S_LOCK**, **X_LOCK** * ì˜ë„/스키마 ìž ê¸ˆ: **IX_LOCK**, **IS_LOCK**, **SIX_LOCK**, **SCH_S_LOCK**, **SCH_M_LOCK** * 특수 ìž ê¸ˆ: **BU_LOCK** * ëª¨ë“ ìœ í˜•ì˜ ìž ê¸ˆì€ ì„œë¡œ ì˜í–¥ì„ 미친다. 위ì—서 설명한 ìž ê¸ˆë“¤ì˜ í˜¸í™˜ 관계(lock compatibility)를 ì •ë¦¬í•˜ë©´ ì•„ëž˜ì˜ í‘œì™€ 같다. 호환ëœë‹¤ëŠ” ê²ƒì€ ìž ê¸ˆ ë³´ìœ ìž(lock holder)ê°€ íŠ¹ì • ê°ì²´ì— 대해 íšë“한 ìž ê¸ˆê³¼ 중복하여 ìž ê¸ˆ ìš”ì²ìž(lock requester)ê°€ ìž ê¸ˆì„ íšë“í• ìˆ˜ 있다는 ì˜ë¯¸ì´ë‹¤. **ìž ê¸ˆ 호환성** * **NULL**\: lockì´ ì¡´ìž¬í•˜ëŠ” ìƒíƒœ. (O: TRUE, X: FALSE) +----------------------------------+-----------------------------------------------------------------------------------------------------------+ | | **ìž ê¸ˆ ë³´ìœ ìž(Lock holder)** | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **NULL** | **SCH-S** | **IS** | **S** | **IX** | **BU** | **SIX** | **X** | **SCH-M** | +----------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | **ìž ê¸ˆ ìš”ì²ìž** | **NULL** | O | O | O | O | O | O | O | O | O | | **(Lock requester)** | | | | | | | | | | | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **SCH-S** | O | O | O | O | O | O | O | O | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **IS** | O | O | O | O | O | X | O | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **S** | O | O | O | O | X | X | X | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **IX** | O | O | O | X | O | X | X | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **BU** | O | O | X | X | X | O | X | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **SIX** | O | O | O | X | X | X | X | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **X** | O | O | X | X | X | X | X | X | X | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **SCH-M** | O | X | X | X | X | X | X | X | X | +----------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ **ìž ê¸ˆ 변환 í…Œì´ë¸”** * **NULL**\: 아무 ìž ê¸ˆë„ ì—†ëŠ” ìƒíƒœ +----------------------------------+-----------------------------------------------------------------------------------------------------------+ | | **íšë“ ìž ê¸ˆ 모드(Granted lock mode)** | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **NULL** | **SCH-S** | **IS** | **S** | **IX** | **BU** | **SIX** | **X** | **SCH-M** | +----------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | **ìš”ì² ìž ê¸ˆ 모드** | **NULL** | NULL | SCH-S | IS | S | IX | BU | SIX | X | SCH-M | | **(Requested lock** +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | **mode)** | **SCH-S** | SCH-S | SCH-S | IS | S | IX | BU | SIX | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **IS** | IS | IS | IS | S | IX | X | SIX | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **S** | S | S | S | S | SIX | X | SIX | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **IX** | IX | IX | IX | SIX | IX | X | SIX | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **BU** | BU | BU | BU | X | BU | BU | BU | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **SIX** | SIX | SIX | SIX | SIX | SIX | X | SIX | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **X** | X | X | X | X | X | X | X | X | SCH-M | | +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ | | **SCH-M** | SCH-M | SCH-M | SCH-M | SCH-M | SCH-M | SCH-M | SCH-M | SCH-M | SCH-M | +----------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ ìž ê¸ˆ 사용 ì˜ˆì œ ++++++++++++++ ë‹¤ìŒ ì˜ˆì œì—서는 REPEATABLE READ(5) 격리 ìˆ˜ì¤€ì´ ì‚¬ìš©ëœë‹¤. READ COMMITTEDì˜ í–‰ ê°±ì‹ ê·œì¹™ì€ ë‹¤ì–‘í•˜ë©°, ë‹¤ìŒ ì„¹ì…˜ì—서 설명한다. ì˜ˆì œì—서는 기존 ìž ê¸ˆì„ ë³´ì—¬ì£¼ê¸° 위해 lockdb ìœ í‹¸ë¦¬í‹°ë¥¼ 사용한다. **ìž ê¸ˆ ì˜ˆì œ:** ë‹¤ìŒ ì˜ˆì œì—서는 REPEATABLE READ(5) 격리 ìˆ˜ì¤€ì´ ì‚¬ìš©ë˜ë©° ë™ì¼í•œ í–‰ì—서 ì½ê¸° ë° ì“°ê¸°ê°€ 차단ë˜ì§€ 않는다는 ê²ƒì„ ë³´ì—¬ì¤€ë‹¤. ê°±ì‹ ì¶©ëŒì´ 시ë„ë˜ê³ ë‘ ë²ˆì§¸ ê°±ì‹ ìž(updater)ê°€ 차단ëœë‹¤. 트랜ìžì…˜ T1ì´ ì»¤ë°‹ë 때 T2ì˜ ì°¨ë‹¨ì´ í•´ì œë˜ì§€ë§Œ 격리 ìˆ˜ì¤€ì˜ ì œì•½ 사í•으로 ì¸í•´ ê°±ì‹ ì€ í—ˆìš©ë˜ì§€ 않는다. T1ì´ ë¡¤ë°±í•˜ëŠ” 경우 T2ê°€ ê°±ì‹ ì„ ì§„í–‰í• ìˆ˜ 있다. +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | T1 | T2 | 설명 | +=========================================================+=========================================================+============================================================================+ | .. code-block :: sql | .. code-block :: sql | AUTOCOMMIT OFF, REPEATABLE READ 로 ì„¤ì • | | | | | | csql> ;au off | csql> ;au off | | | csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;| csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;| | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | | | csql> CREATE TABLE tbl(a INT PRIMARY KEY, b INT); | | | | | | | | csql> INSERT INTO tbl | | | | VALUES (10, 10), | | | | (30, 30), | | | | (50, 50), | | | | (70, 70); | | | | csql> COMMIT; | | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | a = 10ì¸ ì—´ì˜ ì²«ë²ˆì§¸ ë²„ì „ì´ ìž ê¸°ê³ ê°±ì‹ ë¨. a = 90 ì¸ ì—´ì˜ ìƒˆë¡œìš´ ë²„ì „ì´ | | | | ìƒì„±ë˜ê³ ìž ê¹€ :: | | csql> UPDATE tbl SET a = 90 WHERE a = 10; | | | | | | cubrid lockdb: | | | | | | | | OID = 0| 623| 4 | | | | Object type: Class = tbl. | | | | Total mode of holders = IX_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = IX_LOCK | | | | | | | | OID = 0| 650| 5 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 5, delete ID = missing. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = X_LOCK | | | | | | | | OID = 0| 650| 1 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 4, delete ID = 5. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = X_LOCK | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | | .. code-block :: sql | T2는 a<=20 ì¸ ì¡°ê±´ì„ ë§Œì¡±í•˜ëŠ” ëª¨ë“ ì—´ì„ ì½ìŒ. ê°±ì‹ ì„ ìˆ˜í–‰í•œ T1ì´ ì»¤ë°‹ì„ | | | | 하지 않았기 ë•Œë¬¸ì— T2는 a=10ì¸ ì—´ì„ ê³„ì† ë³´ê²Œë˜ê³ ìž ê¸ˆì„ í•˜ì§€ëŠ” ì•ŠìŒ :: | | | csql> SELECT * FROM tbl WHERE a <= 20; | | | | | cubrid lockdb: | | | | | | | a b | OID = 0| 623| 4 | | | ========================== | Object type: Class = tbl. | | | 10 10 | Total mode of holders = IX_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 2, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = IX_LOCK | | | | Tran_index = 2, Granted_mode = IS_LOCK | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | | .. code-block :: sql | T2는 a <= 20ì¸ ëª¨ë“ ì—´ì— ëŒ€í•´ ê°±ì‹ ì„ ì‹œë„한다. | | | | T2ê°€ í´ëž˜ìŠ¤ì˜ ìž ê¸ˆì„ IX_LOCK로 ì—…ê·¸ë ˆì´ë“œí•˜ê³ , ì´ë¯¸ ìž ê¸´ a = 10ì¸ ì—´ì˜ | | | | ê°±ì‹ ì„ ì‹œë„하지만, T1ì— ì˜í•´ ì´ë¯¸ ìž ê¸´ ìƒíƒœì´ë¯€ë¡œ T2는 차단ëœë‹¤. :: | | | csql> UPDATE tbl | | | | SET a = a + 100 | | | | WHERE a <= 20; | | | | | | | | | cubrid lockdb: | | | | OID = 0| 623| 4 | | | | Object type: Class = tbl. | | | | Total mode of holders = IX_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 2, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = IX_LOCK | | | | Tran_index = 2, Granted_mode = IX_LOCK | | | | | | | | OID = 0| 650| 5 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 5, delete ID = missing. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = X_LOCK | | | | | | | | OID = 0| 650| 1 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 4, delete ID = 5. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = X_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 1 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = X_LOCK | | | | LOCK WAITERS: | | | | Tran_index = 2, Blocked_mode = X_LOCK | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | T1ì˜ ìž ê¸ˆì´ í•´ì œë˜ì—ˆë‹¤. | | | | | | csql> COMMIT; | | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | | :: | T2ê°€ 차단ì—서 í•´ì œë˜ì–´ T1ì´ ì´ë¯¸ ê°±ì‹ í•œ ê°œì²´ì˜ ê°±ì‹ ì„ ì‹œë„한다. | | | | REPEATABLE READ 격리 수준ì—서 ì´ê²ƒì€ 허용ë˜ì§€ ì•Šê³ | | | ERROR: Serializable conflict due | 오류가 ì „ì†¡ë¨ | | | to concurrent updates | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ unique ì œì•½ ì¡°ê±´ì„ ë³´í˜¸í•˜ê¸° 위한 ìž ê¸ˆ ------------------------------------- ì´ì „ CUBRID ë²„ì „ì˜ 2단계 ìž ê¸ˆ í”„ë¡œí† ì½œì€ unique ì œì•½ ì¡°ê±´ê³¼ ìƒìœ„ 격리 ì œí•œì„ ë³´í˜¸í•˜ê¸° 위해 ì¸ë±ìФ 키 ìž ê¸ˆì„ ì‚¬ìš©í–ˆë‹¤. CUBRID 10.0ì—서는 키 ìž ê¸ˆì´ ì œê±°ë˜ì—ˆë‹¤. 격리 수준 ì œí•œì€ MVCC 스냅샷으로 í•´ê²°ë˜ì—ˆì§€ë§Œ unique ì œì•½ ì¡°ê±´ì—는 ì—¬ì „ížˆ íŠ¹ì • ìœ í˜•ì˜ ë³´í˜¸ê°€ 필요했다. MVCC는 행처럼 ê³ ìœ ì¸ë±ìŠ¤ê°€ ë™ì‹œì— 여러 ë²„ì „ì„ ìœ ì§€í•˜ë¯€ë¡œ ê°ê° 다른 트랜ìžì…˜ì—서 ë³¼ 수 있다. 여러 ë²„ì „ 중 하나는 마지막 ë²„ì „ì´ê³ , 나머지 ë²„ì „ë“¤ì€ ë¹„ê°€ì‹œí™”ëœ í›„ **VACUUM** ì— ì˜í•´ ì œê±°ë 때까지 ì¼ì‹œì 으로 ìœ ì§€ëœë‹¤. unique ì œì•½ ì¡°ê±´ì„ ë³´í˜¸í•˜ëŠ” ê·œì¹™ì€ í‚¤ë¥¼ ìˆ˜ì •í•˜ë ¤ëŠ” ëª¨ë“ íŠ¸ëžœìžì…˜ì´ í‚¤ì˜ ë§ˆì§€ë§‰ ë²„ì „ì„ ìž ê·¸ëŠ” 것ì´ë‹¤. 아래 ì˜ˆì œëŠ” ìž ê¸ˆì„ í†µí•´ unique ì œì•½ ì¡°ê±´ 위반 방지를 위해 REPEATABLE READ 격리 ìˆ˜ì¤€ì„ ì‚¬ìš©í•œë‹¤. +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | T1 | T2 | 설명 | +=========================================================+=========================================================+============================================================================+ | .. code-block :: sql | .. code-block :: sql | AUTOCOMMIT OFF, REPEATABLE READ 로 ì„¤ì • | | | | | | csql> ;au off | csql> ;au off | | | csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;| csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;| | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | | | csql> CREATE TABLE tbl(a INT PRIMARY KEY, b INT); | | | | | | | | csql> INSERT INTO tbl | | | | VALUES (10, 10), | | | | (30, 30), | | | | (50, 50), | | | | (70, 70); | | | | csql> COMMIT; | | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | T1ì´ í…Œì´ë¸”ì— ìƒˆë¡œìš´ ì—´ì„ ì‚½ìž…í•˜ê³ ìž ê¸ˆìœ¼ë¡œì¨ ê¸°ë³¸í‚¤ 20ì€ ë³´í˜¸ëœë‹¤. | | | | | | csql> INSERT INTO tbl VALUES (20, 20); | | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | | .. code-block :: sql | T2는 í…Œì´ë¸”ì— ìƒˆë¡œìš´ ì—´ì„ ì‚½ìž…í•˜ê³ ìž ê¸ˆì„ ìš”ì²í•œë‹¤. | | | | 하지만, T2ê°€ ê¸°ë³¸í‚¤ì— ìƒˆë¡œìš´ ì—´ì„ ì‚½ìž…í•˜ë ¤ê³ í• ë•Œ, | | | INSERT INTO tbl VALUES (20, 120); | ì´ë¯¸ 기본키 20ì´ ì¡´ìž¬í•˜ê¸° ë•Œë¬¸ì— T2는 T1ì´ ì»¤ë°‹í• ë•Œê¹Œì§€ 차단ëœë‹¤. :: | | | | | | | | | | | | cubrid lockdb: | | | | | | | | OID = 0| 623| 4 | | | | Object type: Class = tbl. | | | | Total mode of holders = IX_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 2, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = IX_LOCK | | | | Tran_index = 2, Granted_mode = IX_LOCK | | | | | | | | OID = 0| 650| 5 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 5, delete ID = missing. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = X_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 1 | | | | LOCK HOLDERS: | | | | Tran_index = 1, Granted_mode = X_LOCK | | | | LOCK WAITERS: | | | | Tran_index = 1, Blocked_mode = X_LOCK | | | | | | | | OID = 0| 650| 6 | | | | Object type: Instance of class ( 0| 623| 4) = tbl. | | | | MVCC info: insert ID = 6, delete ID = missing. | | | | Total mode of holders = X_LOCK, | | | | Total mode of waiters = NULL_LOCK. | | | | Num holders= 1, Num blocked-holders= 0, | | | | Num waiters= 0 | | | | LOCK HOLDERS: | | | | Tran_index = 2, Granted_mode = X_LOCK | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | .. code-block :: sql | | T1ì˜ ìž ê¸ˆì´ í•´ì œëœë‹¤. | | | | | | COMMIT; | | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ | | :: | ì°¨ë‹¨ì´ í•´ì œëœ T2는 T1ì´ ì»¤ë°‹í•œ 키로 ì¸í•´ unique ì œì•½ 위반 오류가 ë°œìƒí•œë‹¤. | | | | | | | ERROR: Operation would have caused | | | | one or more unique constraint violations. | | | | INDEX pk_tbl_a(B+tree: 0|186|640) | | | | ON CLASS tbl(CLASS_OID: 0|623|4). | | | | key: 20(OID: 0|650|6). | | +---------------------------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------------+ 트랜ìžì…˜ êµì°© ìƒíƒœ(deadlock) ---------------------------- êµì°© ìƒíƒœ(deadlock)는 둘 ì´ìƒì˜ 트랜ìžì…˜ì´ 서로 ë§žë¬¼ë ¤ ìƒëŒ€ë°©ì˜ ìž ê¸ˆì´ í•´ì œë˜ê¸°ë¥¼ 기다리는 ìƒíƒœì´ë‹¤. ì´ëŸ¬í•œ êµì°© ìƒíƒœì—서는 서로가 ìƒëŒ€ë°©ì˜ 작업 ìˆ˜í–‰ì„ ì°¨ë‹¨í•˜ê¸° ë•Œë¬¸ì— CUBRID는 트랜ìžì…˜ 중 하나를 롤백시켜 êµì°© ìƒíƒœë¥¼ 해결한다. 롤백ë˜ëŠ” 트랜ìžì…˜ì€ ì¼ë°˜ì 으로 가장 ì ì€ ê°±ì‹ ì„ ìˆ˜í–‰í•œ 것ì¸ë° 보통 가장 ìµœê·¼ì— ì‹œìž‘ëœ íŠ¸ëžœìžì…˜ì´ë‹¤. ì‹œìŠ¤í…œì— ì˜í•´ 트랜ìžì…˜ì´ 롤백ë˜ìžë§ˆìž ê·¸ 트랜ìžì…˜ì´ ê°€ì§€ê³ ìžˆë˜ ìž ê¸ˆì´ í•´ì œë˜ê³ êµì°© ìƒíƒœì— ìžˆë˜ ë‹¤ë¥¸ 트랜ìžì…˜ì´ ì§„í–‰ë˜ë„ë¡ í—ˆê°€ëœë‹¤. ì´ëŸ¬í•œ êµì°© ìƒíƒœ ë°œìƒì€ ì˜ˆì¸¡í• ìˆ˜ 없지만 가급ì êµì°© ìƒíƒœê°€ ë°œìƒí•˜ì§€ 않ë„ë¡ í•˜ë ¤ë©´, ì¸ë±ìŠ¤ë¥¼ ì„¤ì •í•˜ì—¬ ìž ê¸ˆì´ ì„¤ì •ë˜ëŠ” 범위를 줄ì´ê±°ë‚˜ 트랜ìžì…˜ì„ 짧게 만들거나 트랜ìžì…˜ 격리 수준(isolation level)ì„ ë‚®ê²Œ ì„¤ì •í•˜ëŠ” ê²ƒì´ ì¢‹ë‹¤. ì—러 심ê°ì„± ìˆ˜ì¤€ì„ ì„¤ì •í•˜ëŠ” 시스템 파ë¼ë¯¸í„°ì¸ **error_log_level** ì˜ ê°’ì„ NOTIFICATION으로 ì„¤ì •í•˜ë©´ êµì°© ìƒíƒœ ë°œìƒ ì‹œ 서버 ì—러 로그 파ì¼ì— ìž ê¸ˆ ê´€ë ¨ ì •ë³´ê°€ 기ë¡ëœë‹¤. ì´ì „ ë²„ì „ì— ë¹„í•´ CUBRID 10.0ì€ ë” ì´ìƒ ì¸ë±ìФ 키 ìž ê¸ˆì„ ì‚¬ìš©í•˜ì—¬ ì¸ë±ìŠ¤ë¥¼ ì½ê³ ì“°ì§€ 않으므로 êµì°© ìƒíƒœ ë°œìƒì´ í˜„ì €ížˆ 줄어들었다. êµì°© ìƒíƒœê°€ ìžì£¼ ë°œìƒí•˜ì§€ 않는 ë˜ ë‹¤ë¥¸ ì´ìœ 는 ì´ì „ CUBRID ë²„ì „ì€ ì¼ì • ë²”ìœ„ì˜ ì¸ë±ìŠ¤ë¥¼ ì½ì„ 때 ë†’ì€ ê²©ë¦¬ 수준으로 ì¸í•´ 여러 ê°ì²´ë“¤ì„ ìž ê¶œì§€ë§Œ, CUBRID 10.0ì€ ë” ì´ìƒ ìž ê¸ˆì„ ì‚¬ìš©í•˜ì§€ 않기 때문ì´ë‹¤. 그러나 서로 다른 ë‘ ê°œì˜ íŠ¸ëžœìžì…˜ì—서 ë™ì¼í•œ ê°ì²´ë¥¼ 다른 순서로 ê°±ì‹ í• ê²½ìš° ì—¬ì „ížˆ êµì°© ìƒíƒœê°€ ë°œìƒí• ê°€ëŠ¥ì„±ì´ ë‚¨ì•„ 있다. **ì˜ˆì œ** +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | session 1 | session 2 | +====================================================================================================+====================================================================================================+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> set transaction isolation level REPEATABLE READ; | csql> set transaction isolation level REPEATABLE READ; | | | | | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> CREATE TABLE lock_tbl(host_year INTEGER, | | | nation_code CHAR(3)); | | | csql> INSERT INTO lock_tbl VALUES (2004, 'KOR'); | | | csql> INSERT INTO lock_tbl VALUES (2004, 'USA'); | | | csql> INSERT INTO lock_tbl VALUES (2004, 'GER'); | | | csql> INSERT INTO lock_tbl VALUES (2008, 'GER'); | | | csql> COMMIT; | | | | | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> DELETE FROM lock_tbl WHERE nation_code = 'KOR'; | csql> DELETE FROM lock_tbl WHERE nation_code = 'GER'; | | | | | /* The two transactions lock different objects | | | * and they do not block each-other. | | | */ | | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> DELETE FROM lock_tbl WHERE host_year=2008; | | | | | | /* T1 want's to modify a row locked by T2 and is blocked */ | | | | | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> DELETE FROM lock_tbl WHERE host_year = 2004; | | | | | | /* T2 now want to delete the row blocked by T1 | | | * and a deadlock is created. | | | */ | | | | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ | :: | :: | | | | | ERROR: Your transaction (index 1, dba@ 090205|4760) | /* T2 is unblocked and proceeds on modifying its rows. */ | | has been unilaterally aborted by the system. | | | | | | /* System rolled back the transaction 1 to resolve a deadlock */ | | | | | +----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ 트랜ìžì…˜ ìž ê¸ˆ 타임아웃 ---------------------- CUBRID는 트랜ìžì…˜ ìž ê¸ˆ ì„¤ì •ì´ í—ˆìš©ë 때까지 ìž ê¸ˆì„ ëŒ€ê¸°í•˜ëŠ” ì‹œê°„ì„ ì„¤ì •í•˜ëŠ” ìž ê¸ˆ 타임아웃(lock timeout) ê¸°ëŠ¥ì„ ì œê³µí•œë‹¤. 만약 ì„¤ì •ëœ ìž ê¸ˆ 타임아웃 시간 ì´ë‚´ì— ìž ê¸ˆì´ í—ˆìš©ë˜ì§€ 않으면, ìž ê¸ˆ 타임아웃 ì‹œê°„ì´ ê²½ê³¼ëœ ì‹œì ì— í•´ë‹¹ 트랜ìžì…˜ì„ ë¡¤ë°±ì‹œí‚¤ê³ ì—러를 ì¶œë ¥í•œë‹¤. ë˜í•œ, ìž ê¸ˆ 타임아웃 시간 ì´ë‚´ì— 트랜ìžì…˜ êµì°© ìƒíƒœê°€ ë°œìƒí•˜ë©´, CUBRID는 êµì°© ìƒíƒœì— 있는 여러 트랜ìžì…˜ 중 ëŒ€ê¸°ì‹œê°„ì´ íƒ€ìž„ì•„ì›ƒ ì‹œê°„ì— ê°€ê¹Œìš´ 트랜ìžì…˜ì„ 롤백시킨다. **ìž ê¸ˆ 타임아웃 ê°’ ì„¤ì •** **$CUBRID/conf/cubrid.conf** íŒŒì¼ ë‚´ì˜ ì‹œìŠ¤í…œ 파ë¼ë¯¸í„° **lock_timeout** ë˜ëŠ” **SET TRANSACTION** êµ¬ë¬¸ì„ í†µí•´ ì‘ìš© í”„ë¡œê·¸ëž¨ì´ ìž ê¸ˆì„ ëŒ€ê¸°í•˜ëŠ” 타임아웃 시간(ì´ˆ 단위)ì„ ì„¤ì •í•˜ë©°, ì„¤ì •ëœ ì‹œê°„ì´ ê²½ê³¼ëœ ì´í›„ì—는 해당 트랜ìžì…˜ì„ ë¡¤ë°±ì‹œí‚¤ê³ ì—러를 ì¶œë ¥í•œë‹¤. **lock_timeout** 파ë¼ë¯¸í„°ì˜ ê¸°ë³¸ê°’ì€ **-1** ì´ë©°, ì´ëŠ” 트랜ìžì…˜ ìž ê¸ˆì´ í—ˆìš©ë˜ëŠ” 시ì 까지 ë¬´í•œì • 대기한다는 ì˜ë¯¸ì´ë‹¤. ë”°ë¼ì„œ, 사용ìžëŠ” ì‘ìš© í”„ë¡œê·¸ëž¨ì˜ íŠ¸ëžœìžì…˜ íŒ¨í„´ì— ë§žê²Œ ì´ ê°’ì„ ë³€ê²½í• ìˆ˜ 있다. 만약, ìž ê¸ˆ 타임아웃 ê°’ì´ 0으로 ì„¤ì •ë˜ë©´ ìž ê¸ˆì´ ë°œìƒí•˜ëŠ” 즉시 ì—러 메시지가 ì¶œë ¥ë 것ì´ë‹¤. :: SET TRANSACTION LOCK TIMEOUT timeout_spec [ ; ] timeout_spec: - INFINITE - OFF - unsigned_integer - variable * **INFINITE** : 트랜ìžì…˜ ìž ê¸ˆì´ í—ˆìš©ë 때까지 ë¬´í•œì • 대기한다. 시스템 파ë¼ë¯¸í„° **lock_timeout**\ ì„ -1로 ì„¤ì •í•œ 것과 같다. * **OFF** : ìž ê¸ˆì„ ëŒ€ê¸°í•˜ì§€ ì•Šê³ , 해당 트랜ìžì…˜ì„ 롤백시킨 후 ì—러 메시지를 ì¶œë ¥í•œë‹¤. 시스템 파ë¼ë¯¸í„° **lock_timeout**\ ì„ 0으로 ì„¤ì •í•œ 것과 같다. * *unsigned_integer* : ì´ˆ 단위로 ì„¤ì •ë˜ë©°, ì„¤ì •ëœ ì‹œê°„ë§Œí¼ íŠ¸ëžœìžì…˜ ìž ê¸ˆì„ ëŒ€ê¸°í•œë‹¤. * *variable* : 변수를 ì§€ì •í• ìˆ˜ 있으며, ë³€ìˆ˜ì— ì €ìž¥ëœ ê°’ë§Œí¼ íŠ¸ëžœìžì…˜ ìž ê¸ˆì„ ëŒ€ê¸°í•œë‹¤. **ì˜ˆì œ 1** :: vi $CUBRID/conf/cubrid.conf ... lock_timeout = 10s ... **ì˜ˆì œ 2** :: SET TRANSACTION LOCK TIMEOUT 10; **ìž ê¸ˆ 타임아웃 ê°’ 확ì¸** **GET TRANSACTION** ë¬¸ì„ ì´ìš©í•˜ì—¬ 현재 ì‘ìš© í”„ë¡œê·¸ëž¨ì´ ì„¤ì •ëœ ìž ê¸ˆ 타임아웃 ê°’ì„ í™•ì¸í• 수 ìžˆê³ , ì´ ê°’ì„ ë³€ìˆ˜ì— ì €ìž¥í• ìˆ˜ë„ ìžˆë‹¤. :: GET TRANSACTION LOCK TIMEOUT [ { INTO | TO } variable ] [ ; ] **ì˜ˆì œ** :: GET TRANSACTION LOCK TIMEOUT; Result =============== 1.000000e+001 **ìž ê¸ˆ 타임아웃 ì—러 메시지 확ì¸ê³¼ 조치 방법** 다른 트랜ìžì…˜ì˜ ìž ê¸ˆì´ í•´ì œë˜ê¸°ë¥¼ ëŒ€ê¸°í•˜ë˜ íŠ¸ëžœìžì…˜ì— 대해 ìž ê¸ˆ íƒ€ìž„ì•„ì›ƒì´ ë°œìƒí•˜ë©´, 아래와 ê°™ì€ ì—러 메시지를 ì¶œë ¥í•œë‹¤. :: Your transaction (index 2, user1@host1|9808) timed out waiting on IX_LOCK lock on class tbl. You are waiting for user(s) user1@host1|csql(9807), user1@host1|csql(9805) to finish. * Your transaction(index 2 ...) : ìž ê¸ˆì„ ëŒ€ê¸°í•˜ë‹¤ê°€ 타임아웃으로 ë¡¤ë°±ëœ íŠ¸ëžœìžì…˜ì˜ ì¸ë±ìŠ¤ê°€ 2ë¼ëŠ” ì˜ë¯¸ì´ë‹¤. 트랜ìžì…˜ ì¸ë±ìŠ¤ëŠ” í´ë¼ì´ì–¸íŠ¸ê°€ ë°ì´í„°ë² ì´ìФ ì„œë²„ì— ì ‘ì†í•˜ì˜€ì„ 때 순차ì 으로 í• ë‹¹ë˜ëŠ” 번호ì´ë‹¤. ì´ëŠ” **cubrid lockdb** ìœ í‹¸ë¦¬í‹° ì‹¤í–‰ì„ í†µí•´ì„œë„ í™•ì¸í• 수 있다. * (... user1\@host1|9808) : *user1* 는 í´ë¼ì´ì–¸íŠ¸ì˜ ë¡œê·¸ì¸ ì•„ì´ë””ì´ê³ , @ì˜ ë’· ë¶€ë¶„ì€ í´ë¼ì´ì–¸íŠ¸ê°€ ìˆ˜í–‰ëœ í˜¸ìŠ¤íŠ¸ ì´ë¦„ì´ë‹¤. ë˜í•œ | ì˜ ë’· ë¶€ë¶„ì€ í´ë¼ì´ì–¸íŠ¸ì˜ í”„ë¡œì„¸ìŠ¤ ID(PID)ì´ë‹¤. * IX_LOCK : íŠ¹ì • í–‰ì— ë°°íƒ€ ìž ê¸ˆì´ ì„¤ì •ë¨ì— ë”°ë¼ ìƒìœ„ ê°ì²´ì¸ í…Œì´ë¸”ì— ì˜ë„ 배타 ìž ê¸ˆì´ ì„¤ì •ëœë‹¤. ì´ì— 관한 ìƒì„¸í•œ ì„¤ëª…ì€ :ref:`lock-mode` ì„ ì°¸ê³ í•œë‹¤. * user1@host1|csql(9807), user1@host1|csql(9805) : **IX_LOCK** ìž ê¸ˆì„ ì„¤ì •í•˜ê¸° 위해 종료ë˜ê¸°ë¥¼ 기다리는 다른 트랜ìžì…˜ë“¤ì´ë‹¤. 즉, ìœ„ì˜ ìž ê¸ˆ ì—러 메시지는 "다른 트랜ìžì…˜ë“¤ì´ *participant* í…Œì´ë¸”ì˜ íŠ¹ì • í–‰ì— **X_LOCK** ì„ ì ìœ í•˜ê³ ìžˆìœ¼ë¯€ë¡œ, *host1* 호스트ì—서 ìˆ˜í–‰ëœ íŠ¸ëžœìžì…˜ 3ì€ ìž ê¸ˆì´ í•´ì œë˜ê¸°ë¥¼ 기다리다가 ì œí•œ ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆë‹¤."로 í•´ì„í• ìˆ˜ 있다. 만약, ì—러 ë©”ì‹œì§€ì— ëª…ì‹œëœ íŠ¸ëžœìžì…˜ì˜ ìž ê¸ˆ ì •ë³´ë¥¼ 확ì¸í•˜ê³ ìž í•œë‹¤ë©´, **cubrid lockdb** ìœ í‹¸ë¦¬í‹°ë¥¼ 통해 현재 **X_LOCK** ì´ ì„¤ì •ë˜ì–´ 있는 íŠ¹ì • í–‰ì˜ OID ê°’(예: 0|636|34)ì„ ê²€ìƒ‰í•˜ì—¬ 현재 ìž ê¸ˆì„ ì ìœ ì¤‘ì¸ íŠ¸ëžœìžì…˜ ID, í´ë¼ì´ì–¸íЏ 프로그램명 ë° í”„ë¡œì„¸ìŠ¤ ID(PID)를 확ì¸í• 수 있다. ì´ì— 관한 ìƒì„¸í•œ ì„¤ëª…ì€ :ref:`lockdb` ìƒíƒœ í™•ì¸ ì„ ì°¸ê³ í•œë‹¤. CUBRID Managerì—서 트랜ìžì…˜ ìž ê¸ˆ ì •ë³´ë¥¼ 확ì¸í• ìˆ˜ë„ ìžˆë‹¤. ì´ì²˜ëŸ¼ 트랜ìžì…˜ì˜ ìž ê¸ˆ ì •ë³´ë¥¼ 확ì¸í•œ 후ì—는 SQL 로그를 통해 커밋ë˜ì§€ ì•Šì€ ì§ˆì˜ë¬¸ì„ 확ì¸í•˜ì—¬ 트랜ìžì…˜ì„ ì •ë¦¬í• ìˆ˜ 있다. SQL 로그를 확ì¸í•˜ëŠ” ë°©ë²•ì€ :ref:`broker-logs`\ 를 ì°¸ê³ í•œë‹¤. ë˜í•œ, **cubrid killtran** ìœ í‹¸ë¦¬í‹°ë¥¼ 통해 ë¬¸ì œê°€ ë˜ëŠ” 트랜ìžì…˜ì„ ê°•ì œ ì¢…ë£Œí• ìˆ˜ 있으며, ì´ì— 관한 ìƒì„¸í•œ ì„¤ëª…ì€ :ref:`killtran` 를 ì°¸ê³ í•œë‹¤. .. _transaction-isolation-level: 트랜ìžì…˜ 격리 수준 ================== 트랜ìžì…˜ì˜ 격리 ìˆ˜ì¤€ì€ íŠ¸ëžœìžì…˜ì´ ë™ì‹œì— ì§„í–‰ ì¤‘ì¸ ë‹¤ë¥¸ 트랜ìžì…˜ì— ì˜í•´ ê°„ì„받는 ì •ë„를 ì˜ë¯¸í•˜ë©°, 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì´ ë†’ì„ìˆ˜ë¡ íŠ¸ëžœìžì…˜ ê°„ ê°„ì„ì´ ì 으며 ì§ë ¬ì ì´ê³ , 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì´ ë‚®ì„ìˆ˜ë¡ íŠ¸ëžœìžì…˜ ê°„ ê°„ì„ì€ ë§Žìœ¼ë‚˜ ë†’ì€ ë™ì‹œì„±ì„ 보장한다. 사용ìžëŠ” ì ìš©í•˜ê³ ìž í•˜ëŠ” ì„œë¹„ìŠ¤ì˜ íŠ¹ì„±ì— ë”°ë¼ ê²©ë¦¬ ìˆ˜ì¤€ì„ ì ì ˆížˆ ì„¤ì •í•¨ìœ¼ë¡œì¨ ë°ì´í„°ë² ì´ìŠ¤ì˜ ì¼ê´€ì„±(consistency)ê³¼ ë™ì‹œì„±(concurrency)ì„ ì¡°ì •í• ìˆ˜ 있다. .. note:: ì§€ì›ë˜ëŠ” ëª¨ë“ ê²©ë¦¬ 수준ì—서 트랜ìžì…˜ì€ 복구 가능하다. ì´ëŠ” 트랜ìžì…˜ì´ ë나기 ì „ì—는 ê°±ì‹ ì„ ì»¤ë°‹í•˜ì§€ 않기 때문ì´ë‹¤. .. _set-transaction-isolation-level: 트랜ìžì…˜ 격리 수준 ì„¤ì • ----------------------- **$CUBRID/conf/cubrid.conf** ì˜ **isolation_level** ë° **SET TRANSACTION** ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì„ ì„¤ì •í• ìˆ˜ 있다. 기본ì 으로 **READ COMMITTED** ìˆ˜ì¤€ì´ ì„¤ì •ë˜ì–´ 있으며, 4~6 수준 중ì—서 4 ìˆ˜ì¤€ì— í•´ë‹¹í•œë‹¤(1~3 ìˆ˜ì¤€ì€ CUBRIDì˜ ì´ì „ ë²„ì „ì—서 사용ë˜ì—ˆìœ¼ë©° ë” ì´ìƒ 사용하지 않ìŒ). ì´ì— 관한 ìƒì„¸í•œ ì„¤ëª…ì€ :ref:`database-concurrency` ì„ ì°¸ê³ í•œë‹¤. :: SET TRANSACTION ISOLATION LEVEL isolation_level_spec ; isolation_level_spec: SERIALIZABLE | 6 REPETABLE READ | 5 READ COMMITTED | CURSOR STABILITY | 4 **ì˜ˆì œ 1** :: vi $CUBRID/conf/cubrid.conf ... isolation_level = 4 ... -- or isolation_level = "TRAN_READ_COMMITTED" **ì˜ˆì œ 2** :: SET TRANSACTION ISOLATION LEVEL 4; -- or SET TRANSACTION ISOLATION LEVEL READ COMMITTED; **CUBRIDê°€ ì§€ì›í•˜ëŠ” 격리 수준** +-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 격리 수준 ì´ë¦„ | 설명 | +=======================+=====================================================================================================================================================================================+ | READ COMMITTED (4) | 트랜ìžì…˜ T1ì´ í…Œì´ë¸” A를 조회하는 ë™ì•ˆ 다른 트랜ìžì…˜T2는 í…Œì´ë¸”Aì˜ ìŠ¤í‚¤ë§ˆë¥¼ ê°±ì‹ í• ìˆ˜ 없다. | | | 트랜ìžì…˜ T1ì€ ì—¬ëŸ¬ë²ˆ R를 조회하는 ì¤‘ì— íŠ¸ëžœìžì…˜ T2ê°€ ê°±ì‹ í•˜ê³ ì»¤ë°‹í•œ R'를 ì½ê¸°(반복 불가능한 ì½ê¸°)를 ê²½í—˜í• ìˆ˜ 있다. | +-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | REPEATABLE READ (5) | 트랜ìžì…˜ T1ì´ í…Œì´ë¸” A를 조회하는 ë™ì•ˆ 다른 트랜ìžì…˜T2는 í…Œì´ë¸” Aì˜ ìŠ¤í‚¤ë§ˆë¥¼ ê°±ì‹ í• ìˆ˜ 없다. | | | 트랜ìžì…˜ T1ì€ íŠ¹ì • ë ˆì½”ë“œë¥¼ 여러번 조회하는 ì¤‘ì— ë‹¤ë¥¸ 트랜ìžì…˜ T2ê°€ 삽입한 ë ˆì½”ë“œ Rì— ëŒ€í•´ ìœ ë ¹ ì½ê¸°ë¥¼ ê²½í—˜í• ìˆ˜ 있다. | +-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | SERIALIZABLE (6) | ì§€ì› ì˜ˆì • - ìƒì„¸í•œ 사í•ì€ ë‹¤ìŒì„ ì°¸ê³ í•œë‹¤. :ref:`isolation-level-6` | +-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ì‘ìš© 프로그램ì—서 트랜ìžì…˜ 수행 ì¤‘ì— ê²©ë¦¬ ìˆ˜ì¤€ì´ ë³€ê²½ë˜ë©´, 수행 ì¤‘ì¸ íŠ¸ëžœìžì…˜ì˜ ë‚¨ì€ ë¶€ë¶„ë¶€í„° ë³€ê²½ëœ ê²©ë¦¬ ìˆ˜ì¤€ì´ ì ìš©ëœë‹¤. ì´ì²˜ëŸ¼ ì„¤ì •ëœ ê²©ë¦¬ ìˆ˜ì¤€ì´ í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ ì „ì²´ì— ì ìš©ë˜ëŠ” ê²ƒì´ ì•„ë‹ˆë¼ íŠ¸ëžœìžì…˜ ì¤‘ê°„ì— ë³€ê²½ë˜ì–´ ì ìš©ë 수 있기 때문ì—, 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì€ íŠ¸ëžœìžì…˜ 시작 시ì (커밋, 롤백, ë˜ëŠ” 시스템 재시작 ì´í›„)ì— ë³€ê²½í•˜ëŠ” ê²ƒì´ ë°”ëžŒì§í•˜ë‹¤. 트랜ìžì…˜ 격리 수준 ê°’ í™•ì¸ -------------------------- **GET TRANSACTION ISOLATION LEVEL** ë¬¸ì„ ì´ìš©í•˜ì—¬ 현재 í´ë¼ì´ì–¸íŠ¸ì— ì„¤ì •ëœ ê²©ë¦¬ 수준 ê°’ì„ ì¶œë ¥í•˜ê±°ë‚˜ *variable* ì— í• ë‹¹í• ìˆ˜ 있다. 아래는 격리 ìˆ˜ì¤€ì„ í™•ì¸í•˜ê¸° 위한 구문ì´ë‹¤. :: GET TRANSACTION ISOLATION LEVEL [ { INTO | TO } variable ] [ ; ] .. code-block:: sql GET TRANSACTION ISOLATION LEVEL; :: Result ============= READ COMMITTED .. _isolation-level-4: READ COMMITTED 격리 수준 ------------------------ 비êµì ë‚®ì€ ê²©ë¦¬ 수준(4)으로서 ë”í‹° ì½ê¸°ëŠ” ë°œìƒí•˜ì§€ 않지만, 반복 불가능한 ì½ê¸°ì™€ ìœ ë ¹ ì½ê¸°ëŠ” ë°œìƒí• 수 있다. 즉, 트랜ìžì…˜ *T1* ì´ í•˜ë‚˜ì˜ ê°ì²´ë¥¼ 반복하여 조회하는 ë™ì•ˆ 다른 트랜ìžì…˜ *T2* ì—ì„œì˜ ì‚½ìž… ë˜ëŠ” ê°±ì‹ ì´ í—ˆìš©ë˜ì–´, 트랜ìžì…˜ *T1* ì´ ë‹¤ë¥¸ ê°’ì„ ì½ì„ 수 있다는 ì˜ë¯¸ì´ë‹¤. 다ìŒê³¼ ê°™ì€ ê·œì¹™ì´ ì ìš©ëœë‹¤. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 삽입ë˜ëŠ” ë ˆì½”ë“œë¥¼ ì½ê±°ë‚˜ ìˆ˜ì •í• ìˆ˜ 없다. ëŒ€ì‹ ë ˆì½”ë“œê°€ 무시ëœë‹¤. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 ê°±ì‹ í•˜ëŠ” ë ˆì½”ë“œë¥¼ ì½ì„ 수 있으며, ë ˆì½”ë“œì˜ ë§ˆì§€ë§‰ ì»¤ë°‹ëœ ë²„ì „ì„ í™•ì¸í•œë‹¤(커밋ë˜ì§€ ì•Šì€ ë²„ì „ì€ ë³¼ 수 ì—†ìŒ). * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 ê°±ì‹ ì¤‘ì¸ ë ˆì½”ë“œë¥¼ ìˆ˜ì •í• ìˆ˜ 없다. *T1* ì€ *T2* ê°€ 커밋ë˜ê¸°ë¥¼ 기다린 후 ì»¤ë°‹ì´ ë˜ë©´ ë ˆì½”ë“œ ê°’ì„ ë‹¤ì‹œ í‰ê°€í•œë‹¤. 재í‰ê°€ì‹œ ì 합하면 *T1* ì€ ë ˆì½”ë“œë¥¼ ìˆ˜ì •í•˜ê³ ì 합하지 않으면 무시한다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ ë ˆì½”ë“œë¥¼ ìˆ˜ì •í• ìˆ˜ 있다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ í…Œì´ë¸”ì— ë ˆì½”ë“œë¥¼ ê°±ì‹ /ì‚½ìž…í• ìˆ˜ 있다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ í…Œì´ë¸”ì˜ ìŠ¤í‚¤ë§ˆë¥¼ ë³€ê²½í• ìˆ˜ 없다. * 트랜ìžì…˜ *T1* ì´ ìˆ˜í–‰ëœ ê°ê°ì˜ 질ì˜ë¬¸ì— 새로운 ìŠ¤ëƒ…ìƒ·ì„ ìƒì„±í•˜ë¯€ë¡œ ìœ ë ¹ ì½ê¸° ë˜ëŠ” ë°˜ë³µí• ìˆ˜ 없는 ì½ê¸°ëŠ” ë°œìƒí• 수 있다. ì´ ê²©ë¦¬ ìˆ˜ì¤€ì€ ë°°íƒ€ ìž ê¸ˆì— ëŒ€í•´ MVCC ìž ê¸ˆ í”„ë¡œí† ì½œì„ ë”°ë¥¸ë‹¤. í–‰ì— ê³µìœ ìž ê¸ˆì€ í•„ìš”í•˜ì§€ 않지만 í…Œì´ë¸”ì— ëŒ€í•œ ì˜ë„ ìž ê¸ˆì€ ìŠ¤í‚¤ë§ˆì— ëŒ€í•œ 반복 가능한 ì½ê¸°ë¥¼ 보장하기 위하여 트랜ìžì…˜ì´ 종료ë 때 í•´ì œëœë‹¤. *예:* ë‹¤ìŒ ì˜ˆì œëŠ” 트랜ìžì…˜ 격리 ìˆ˜ì¤€ì´ **READ COMMITTED** ì¸ ê²½ìš°, 한 트랜ìžì…˜ì´ ê°ì²´ ì½ê¸°ë¥¼ 수행하는 ë™ì•ˆ 다른 트랜ìžì…˜ì´ ë ˆì½”ë“œë¥¼ 추가하거나 ê°±ì‹ í• ìˆ˜ ìžˆê¸°ë•Œë¬¸ì— ìœ ë ¹ ë˜ëŠ” 반복 불가능한 ì½ê¸°ê°€ ë°œìƒí• 수 있ìŒì„ ë³´ì—¬ì£¼ê³ í…Œì´ë¸” 스키마 ê°±ì‹ ì— ëŒ€í•´ì„œëŠ” 반복 가능한 ì½ê¸°ê°€ 보장ëœë‹¤ëŠ” ê²ƒì„ ë³´ì—¬ì¤€ë‹¤. +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | session 1 | session 2 | +=========================================================================+==================================================================================+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED; | csql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED; | | | | | Isolation level set to: | Isolation level set to: | | READ COMMITTED | READ COMMITTED | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> CREATE TABLE isol4_tbl(host_year integer, nation_code char(3)); | | | | | | csql> INSERT INTO isol4_tbl VALUES (2008, 'AUS'); | | | | | | csql> COMMIT; | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol4_tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> INSERT INTO isol4_tbl VALUES (2004, 'AUS'); | | | csql> INSERT INTO isol4_tbl VALUES (2000, 'NED'); | | | csql> COMMIT; | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | /* phantom read occurs because tran 1 committed */ | | | csql> SELECT * FROM isol4_tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'AUS' | | | 2004 'AUS' | | | 2000 'NED' | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> UPDATE isol4_tbl | | | csql> SET nation_code = 'KOR' | | | csql> WHERE host_year = 2008; | | | csql> COMMIT; | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | /* unrepeatable read occurs because tran 1 committed */ | | | csql> SELECT * FROM isol4_tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'KOR' | | | 2004 'AUS' | | | 2000 'NED' | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> ALTER TABLE isol4_tbl ADD COLUMN gold INT; | | | | | | /* unable to alter the table schema until tran 2 committed */ | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | /* repeatable read is ensured while | | | * tran_1 is altering table schema | | | */ | | | | | | csql> SELECT * FROM isol4_tbl; | | | | | | host_year nation_code | | | =================================== | | | 2008 'KOR' | | | 2004 'AUS' | | | 2000 'NED' | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> COMMIT; | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol4_tbl; | | | | | | /* unable to access the table until tran_1 committed */ | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> COMMIT; | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | host_year nation_code gold | | | =================================== | | | 2008 'KOR' NULL | | | 2004 'AUS' NULL | | | 2000 'NED' NULL | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ READ COMMITTED UPDATE RE-EVALUATION +++++++++++++++++++++++++++++++++++ **READ COMMITTED** 격리 ìˆ˜ì¤€ì€ ë™ì‹œì— ë°œìƒí•˜ëŠ” í–‰ ê°±ì‹ ì— ëŒ€í•´ ë†’ì€ ê²©ë¦¬ 수준과 다르게 처리한다. ë†’ì€ ê²©ë¦¬ 수준ì—서는 ë™ì‹œ 트랜ìžì…˜ *T1* ì—서 ì´ë¯¸ ê°±ì‹ í•œ í–‰ì„ *T2* ê°€ ìˆ˜ì •í•˜ë ¤ê³ ì‹œë„하면 *T1* ì´ ì»¤ë°‹ ë˜ëŠ” ë¡¤ë°±í• ë•Œê¹Œì§€ 차단ë˜ë©°, *T1* ì´ ì»¤ë°‹ë˜ë©´ *T2* ê°€ ì§ˆì˜ ìˆ˜í–‰ì„ ì¤‘ë‹¨í•˜ê³ ì§ë ¬í™” 오류가 표시ëœë‹¤. **READ COMMITTED** 격리 수준ì—서는 *T1* ì´ ì»¤ë°‹ë˜ë©´ *T2* ê°€ ì§ˆì˜ ìˆ˜í–‰ì„ ë°”ë¡œ 중단하지 ì•Šê³ ìµœì‹ ë²„ì „ì„ ìž¬ í‰ê°€í•œë‹¤. ì´ì „ ë²„ì „ì„ ì„ íƒí•˜ëŠ” ë° ì‚¬ìš©ëœ ì¡°ê±´ê°’ì´ ìµœì‹ ë²„ì „ì— ëŒ€í•´ì„œë„ ê³„ì† ì ìš©ë˜ë©´ *T2* 는 ìµœì‹ ë²„ì „ì„ ìˆ˜ì •í•œë‹¤. ì¡°ê±´ê°’ì´ ë” ì´ìƒ 만족하지 않으면 *T2* 는 해당 ë ˆì½”ë“œì˜ ìˆ˜ì •ì„ ë¬´ì‹œí•œë‹¤. *예:* +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | session 1 | session 2 | +=========================================================================+==================================================================================+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> SET TRANSACTION ISOLATION LEVEL 4; | csql> SET TRANSACTION ISOLATION LEVEL 4; | | | | | Isolation level set to: | Isolation level set to: | | READ COMMITTED | READ COMMITTED | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> CREATE TABLE isol4_tbl(host_year integer, nation_code char(3)); | | | csql> INSERT INTO isol4_tbl VALUES (2000, 'KOR'); | | | csql> INSERT INTO isol4_tbl VALUES (2004, 'USA'); | | | csql> INSERT INTO isol4_tbl VALUES (2004, 'GER'); | | | csql> INSERT INTO isol4_tbl VALUES (2008, 'GER'); | | | csql> COMMIT; | | | | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> UPDATE isol4_tbl | | | csql> SET host_year = host_year - 4 | | | csql> WHERE nation_code = 'GER'; | | | | | | /* T1 locks and modifies (2004, 'GER') to (2000, 'GER') */ | | | /* T1 locks and modifies (2008, 'GER') to (2004, 'GER') */ | | | | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> UPDATE isol4_tbl | | | csql> SET host_year = host_year + 4 | | | csql> WHERE host_year >= 2004; | | | | | | /* T2 snapshot will try to modify three records: | | | * (2004, 'USA'), (2004, 'GER'), (2008, 'GER') | | | * | | | * T2 locks and modifies (2004, 'USA') to (2008, 'USA') | | | * T2 is blocked on lock on (2004, 'GER'). | | | */ | | | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> COMMIT; | | | | | | /* T1 releases locks on modified rows. */ | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | /* T2 is unblocked and will do the next steps: | | | * | | | * T2 finds (2004, 'GER') has a new version (2000, 'GER') | | | * that doesn't satisfy predicate anymore. | | | * T2 releases the lock on object and ignores it. | | | * | | | * T2 finds (2008, 'GER') has a new version (2004, 'GER') | | | * that still satisfies the predicate. | | | * T2 keeps the lock and changes row to (2008, 'GER') | | | */ | | | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol4_tbl; | | | | | | host_year nation_code | | | =================================== | | | 2000 'KOR' | | | 2000 'GER' | | | 2008 'USA' | | | 2008 'GER' | | | | +-------------------------------------------------------------------------+----------------------------------------------------------------------------------+ .. _isolation-level-5: REPEATABLE READ 격리 수준 ------------------------- REPEATABLE READ 격리 수준(5)ì€ **snapshot isolation** ë•Œë¬¸ì— ë”í‹° ì½ê¸°, 반복 불가능한 ì½ê¸° ë° ìœ ë ¹ ì½ê¸°ê°€ ë°œìƒí•˜ì§€ 않는다. 하지만 완벽하게 **serializable** 하지는 않으므로, *ë™ì‹œì— 실행 ì¤‘ì¸ ë‹¤ë¥¸ 트랜ìžì…˜ì´ 없는* 트랜ìžì…˜ 수행ì´ë¼ê³ ë§í• 수 없으며, **serializable snapshot isolation** ìˆ˜ì¤€ì´ í—ˆìš©í•˜ì§€ 않는 스í 쓰기(write skew)와 ê°™ì€ ë³µìž¡í•œ 예외가 ë°œìƒí• 수 있다. 스í 쓰기는 ë‘ ê°œì˜ íŠ¸ëžœìžì…˜ì´ ë™ì‹œì— 겹치는 ë°ì´í„° ì…‹ì„ ì½ê³ 겹친 ê°ê° 다른 ì˜ì—ì˜ ê°±ì‹ ì„ ìˆ˜í–‰í•˜ì—¬ 다른 사용ìžê°€ 수행한 ê°±ì‹ ì„ í™•ì¸í• 수 없는 현ìƒì´ë‹¤. ì§ë ¬í™” 시스템ì—서는 한 트랜ìžì…˜ì´ ë¨¼ì € ë°œìƒí•˜ê³ ë‘ ë²ˆì§¸ 트랜ìžì…˜ì´ 첫 번째 트랜ìžì…˜ì˜ ê°±ì‹ ì„ í™•ì¸í•˜ê¸° ë•Œë¬¸ì— ì´ëŸ¬í•œ 현ìƒì´ ë°œìƒí•˜ì§€ 않는다. 다ìŒê³¼ ê°™ì€ ê·œì¹™ì´ ì ìš©ëœë‹¤. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 삽입ë˜ëŠ” ë ˆì½”ë“œë¥¼ ì½ê±°ë‚˜ ìˆ˜ì •í• ìˆ˜ 없으며 ëŒ€ì‹ í•´ë‹¹ ë ˆì½”ë“œë¥¼ 무시한다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 ê°±ì‹ ì¤‘ì¸ ë ˆì½”ë“œë¥¼ ì½ì„ 수 있으며, ë ˆì½”ë“œì˜ ë§ˆì§€ë§‰ ì»¤ë°‹ëœ ë²„ì „ì„ í™•ì¸í•œë‹¤. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 ê°±ì‹ ì¤‘ì¸ ë ˆì½”ë“œë¥¼ ìˆ˜ì •í• ìˆ˜ 없다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ ë ˆì½”ë“œë¥¼ ìˆ˜ì •í• ìˆ˜ 있다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ í…Œì´ë¸”ì— ë ˆì½”ë“œë¥¼ ê°±ì‹ /ì‚½ìž…í• ìˆ˜ 있다. * 트랜ìžì…˜ *T1* ì€ ë‹¤ë¥¸ 트랜ìžì…˜ *T2* ì—서 조회 ì¤‘ì¸ í…Œì´ë¸”ì˜ ìŠ¤í‚¤ë§ˆë¥¼ ë³€ê²½í• ìˆ˜ 없다. * 트랜ìžì…˜ *T1* ì€ íŠ¸ëžœìžì…˜ì˜ 수행 ë™ì•ˆì— ìœ íš¨í•œ ê³ ìœ ìŠ¤ëƒ…ìƒ·ì„ ìƒì„±í•œë‹¤. **ì˜ˆì œ** ë‹¤ìŒ ì˜ˆì œëŠ” **snapshot isolation** 으로 ì¸í•´ 반복 불가능한 ì½ê¸° ë° ìœ ë ¹ ì½ê¸°ê°€ ë°œìƒí•˜ì§€ 않는 ê²ƒì„ ë³´ì—¬ì¤€ë‹¤. 그러나 격리 ìˆ˜ì¤€ì´ **serializable** ë˜ì–´ 있지 않기 ë•Œë¬¸ì— ìŠ¤í 쓰기는 ë°œìƒí• 수 있다. +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | session 1 | session 2 | +============================================================================+=============================================================================+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> ;autocommit off | csql> ;autocommit off | | | | | AUTOCOMMIT IS OFF | AUTOCOMMIT IS OFF | | | | | csql> SET TRANSACTION ISOLATION LEVEL 5; | csql> SET TRANSACTION ISOLATION LEVEL 5; | | | | | Isolation level set to: | Isolation level set to: | | REPEATABLE READ | REPEATABLE READ | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> CREATE TABLE isol5_tbl(host_year integer, nation_code char(3)); | | | csql> CREATE UNIQUE INDEX isol5_u_idx | | | on isol5_tbl(nation_code, host_year); | | | csql> INSERT INTO isol5_tbl VALUES (2008, 'AUS'); | | | csql> INSERT INTO isol5_tbl VALUES (2004, 'AUS'); | | | | | | csql> COMMIT; | | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code='AUS'; | | | | | | host_year nation_code | | | =================================== | | | 2004 'AUS' | | | 2008 'AUS' | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> INSERT INTO isol5_tbl VALUES (2004, 'KOR'); | | | csql> INSERT INTO isol5_tbl VALUES (2000, 'AUS'); | | | | | | /* able to insert new rows */ | | | csql> COMMIT; | | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code='AUS'; | | | | | | /* phantom read cannot occur due to snapshot isolation */ | | | | | | host_year nation_code | | | =================================== | | | 2004 'AUS' | | | 2008 'AUS' | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> UPDATE isol5_tbl | | | csql> SET host_year = 2012 | | | csql> WHERE nation_code = 'AUS' and | | | csql> host_year=2008; | | | | | | /* able to update rows viewed by T2 */ | | | csql> COMMIT; | | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS'; | | | | | | /* non-repeatable read cannot occur due to snapshot isolation */ | | | | | | host_year nation_code | | | =================================== | | | 2004 'AUS' | | | 2008 'AUS' | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> COMMIT; | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | .. code-block :: sql | | | | | csql> SELECT * FROM isol5_tbl WHERE host_year >= 2004; | csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS'; | | | | | host_year nation_code | host_year nation_code | | =================================== | =================================== | | 2004 'AUS' | 2000 'AUS' | | 2004 'KOR' | 2004 'AUS' | | 2012 'AUS' | 2012 'AUS' | | | | | csql> UPDATE isol5_tbl | csql> UPDATE isol5_tbl | | csql> SET nation_code = 'USA' | csql> SET nation_code = 'NED' | | csql> WHERE nation_code = 'AUS' and | csql> WHERE nation_code = 'AUS' and | | csql> host_year = 2004; | csql> host_year = 2012; | | | | | csql> COMMIT; | csql> COMMIT; | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | /* T1 and T2 first have selected each 3 throws and rows (2004, 'AUS'), (2012, 'AUS') overlapped. | | * Then T1 modified (2004, 'AUS'), while T2 modified (2012, 'AUS'), without blocking each other. | | * In a serial execution, the result of select query for T1 or T2, whichever executes last, would be different. | | */ | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS'; | | | | | | host_year nation_code | | | =================================== | | | 2000 'AUS' | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> ALTER TABLE isol5_tbl ADD COLUMN gold INT; | | | | | | /* unable to alter the table schema until tran 2 committed */ | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | /* repeatable read is ensured while tran_1 is altering | | | * table schema | | | */ | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS'; | | | | | | host_year nation_code | | | =================================== | | | 2000 'AUS' | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> COMMIT; | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS'; | | | | | | /* unable to access the table until tran_1 committed */ | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | .. code-block :: sql | | | | | | csql> COMMIT; | | | | | | | | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ | | .. code-block :: sql | | | | | | host_year nation_code gold | | | =================================== | | | 2000 'AUS' NULL | +----------------------------------------------------------------------------+-----------------------------------------------------------------------------+ .. _isolation-level-6: SERIALIZABLE 격리 수준 ---------------------- CUBRID 10.0ì˜ **SERIALIZABLE** 격리 ìˆ˜ì¤€ì€ **REPEATABLE READ** 격리 수준과 ë™ì¼í•˜ë‹¤. :ref:`isolation-level-5` ì„¹ì…˜ì— ì„¤ëª…ëœ ëŒ€ë¡œ, SNAPSHOT 격리 수준으로 ì¸í•´ 반복 불가능한 ì½ê¸° ë° ìœ ë ¹ ì½ê¸° 현ìƒì€ ë°œìƒí•˜ì§€ 않지만 스í 쓰기 현ìƒì€ ì—¬ì „ížˆ ë°œìƒí• 수 있다. 스í 쓰기를 방지하기 위해서 ì½ê¸°ì— 대해 ì¸ë±ìФ 키 ìž ê¸ˆì„ ì‚¬ìš©í•˜ê±°ë‚˜, 격리 ì¶©ëŒì„ ë°œìƒí• 수 있는 트랜ìžì…˜ì„ 중단시키는 ë“±ì˜ ë‹¤ì–‘í•œ SERIALIZABLE SNAPSHOT ISOLATION ë°©ë²•ì´ ìžˆë‹¤. 향후 CUBRID ë²„ì „ì—서는 ì´ëŸ° 방법 중 하나를 ì œê³µë ì˜ˆì •ì´ë‹¤. 즉, 기존 ë²„ì „ê³¼ì˜ í˜¸í™˜ì„±ì„ ìœ„í•´ 키워드는 ì œê±°ë˜ì§€ 않았지만 SERIALIZABLEì€ **REPEATABLE READ** 와 ìœ ì‚¬í•˜ë‹¤. .. _dirty-record-flush: CUBRIDì—서 ë”í‹° ë ˆì½”ë“œë¥¼ 다루는 방법 ------------------------------------ CUBRID는 다양한 ìƒí™©ì—서 í´ë¼ì´ì–¸íŠ¸ì˜ ë²„í¼ì— 존재하는 ë”í‹° ë°ì´í„°(ë˜ëŠ” ë”í‹° ë ˆì½”ë“œ)를 ë°ì´í„°ë² ì´ìФ 서버로 ë‚´ë ¤ì“°ê¸°(flush)한다. ì•„ëž˜ì— ëª…ì‹œëœ ìƒí™©ì´ 아닌 경우ì—ë„ ë‚´ë ¤ì“°ê¸°ê°€ ë°œìƒí• 수 있다. * 트랜ìžì…˜ ì»¤ë°‹ì´ ìˆ˜í–‰ë 때 ë”í‹° ë°ì´í„°ëŠ” 서버로 ë‚´ë ¤ì“°ê¸°ëœë‹¤. * í´ë¼ì´ì–¸íŠ¸ì˜ ë²„í¼ì— ì ìž¬ëœ ë°ì´í„°ê°€ ë§Žì€ ê²½ìš°, ì¼ë¶€ ë”í‹° ë°ì´í„°ëŠ” 서버로 ë‚´ë ¤ì“°ê¸°ëœë‹¤. * í…Œì´ë¸” *A* ì˜ ë”í‹° ë°ì´í„°ëŠ” í…Œì´ë¸” *A* ì˜ ìŠ¤í‚¤ë§ˆê°€ ê°±ì‹ ë 때 서버로 ë‚´ë ¤ì“°ê¸°ëœë‹¤. * í…Œì´ë¸” *A* ì˜ ë”í‹° ë°ì´í„°ëŠ” í…Œì´ë¸” *A* ê°€ 조회( **SELECT** )ë 때 서버로 ë‚´ë ¤ì“°ê¸°ëœë‹¤. * ë”í‹° ë°ì´í„°ì˜ ì¼ë¶€ëŠ” 서버 함수가 호출ë 때 ë‚´ë ¤ì“°ê¸°ë 수 있다. 트랜ìžì…˜ 종료와 복구 ==================== CUBRIDì—서 복구 프로세스를 사용하면 소프트웨어 ë˜ëŠ” í•˜ë“œì›¨ì–´ì— ì˜¤ë¥˜ê°€ ë°œìƒí•˜ë”ë¼ë„ ë°ì´í„°ë² ì´ìФì—는 ì˜í–¥ì„ 미치지 않ë„ë¡ í• ìˆ˜ 있다. CUBRIDì—서 ëª¨ë“ ì½ê¸°ì™€ ê°±ì‹ ëª…ë ¹ë¬¸ì€ ì›ìžì„±(atomic)ì„ ë³´ìž¥í•œë‹¤. ì´ê²ƒì€ ëª…ë ¹ë¬¸ë“¤ì´ ì»¤ë°‹ë˜ì–´ ë°ì´í„°ë² ì´ìŠ¤ê°€ ê°±ì‹ ë˜ê±°ë‚˜, 커밋ë˜ì§€ 않아 ê°±ì‹ ì´ ë¬´íš¨í™”ë˜ì–´ì•¼ í•¨ì„ ì˜ë¯¸í•œë‹¤. ì›ìžì„±ì˜ ê°œë…ì€ íŠ¸ëžœìžì…˜ì„ 구성하는 ì—°ì‚°ì˜ ì§‘í•©ìœ¼ë¡œ 확장ëœë‹¤. 트랜ìžì…˜ì€ ì»¤ë°‹ì„ ì„±ê³µí•˜ì—¬ ëª¨ë“ ì˜í–¥ì´ ë°ì´í„°ë² ì´ìŠ¤ì— ì˜êµ¬í™” ë˜ê±°ë‚˜ 아니면 롤백ë˜ì–´ 트랜ìžì…˜ì˜ ëª¨ë“ ì˜í–¥ì´ ì œê±°ë˜ì–´ì•¼ 한다. 트랜ìžì…˜ì˜ ì›ìžì„±ì„ 보장하기 위해서 CUBRID는 ëª¨ë“ íŠ¸ëžœìžì…˜ì˜ ê°±ì‹ ì´ ë””ìŠ¤í¬ì— 쓰여지지 ì•Šì€ ì±„ 오류가 ë°œìƒí• 때마다 ì»¤ë°‹ëœ íŠ¸ëžœìžì…˜ì˜ ì˜í–¥ì„ 다시 ì 용시킨다. ë˜í•œ CUBRID는 사ì´íŠ¸ê°€ 실패(몇몇 트랜ìžì…˜ì´ 커밋ë˜ì§€ 못했거나 ì‘ìš© í”„ë¡œê·¸ëž¨ì´ íŠ¸ëžœìžì…˜ 취소를 ìš”ì²í–ˆì„ 수 있다)í• ë•Œë§ˆë‹¤ ë°ì´í„°ë² ì´ìФì—서 부분ì 으로 ì»¤ë°‹ëœ íŠ¸ëžœìžì…˜ì˜ ì˜í–¥ì„ ì œê±°í•œë‹¤. ì´ëŸ¬í•œ 복구 ê¸°ëŠ¥ì€ ì‘ìš© í”„ë¡œê·¸ëž¨ì´ ì‹œìŠ¤í…œ ì˜¤ë¥˜ì— ë”°ë¼ ì–´ë–»ê²Œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì¼ê´€ì„± 있는 ìƒíƒœë¡œ ë˜ëŒë¦´ ì§€ì— ëŒ€í•œ ë¶€ë‹´ì„ ëœì–´ì¤€ë‹¤. CUBRIDì—서 사용ë˜ëŠ” 복구 ê¸°ëŠ¥ì€ ì–¸ë‘/ë¦¬ë‘ ë¡œê¹… ê¸°ë²•ì„ ê¸°ë°˜ìœ¼ë¡œ 한다. CUBRID는 하드웨어와 소프트웨어 오류가 ë°œìƒí•˜ëŠ” ë™ì•ˆ 트랜ìžì…˜ì˜ ì›ìžì„±ì„ ìœ ì§€í•˜ê¸° 위해서 ìžë™ 복구 ê¸°ë²•ì„ ì œê³µí•œë‹¤. CUBRIDì˜ ë³µêµ¬ ê¸°ëŠ¥ì€ ì‘ìš© 프로그램 ë˜ëŠ” 컴퓨터 ì‹œìŠ¤í…œì˜ ì˜¤ë¥˜ê°€ ë°œìƒí•˜ë”ë¼ë„ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ í•ìƒ ì¼ê´€ëœ ìƒíƒœë¡œ ë˜ëŒë ¤ë†“기 ë•Œë¬¸ì— ì‚¬ìš©ìžëŠ” ë³µêµ¬ì— ëŒ€í•œ ì±…ìž„ì„ ê°€ì§ˆ 필요가 없다. ì´ê²ƒì„ 위해 CUBRID는 시스템ì´ë‚˜ ì‘ìš© í”„ë¡œê·¸ëž¨ì˜ ì‹¤íŒ¨ ë˜ëŠ” 사용ìžì˜ 명시ì ìš”ì²ì— ë”°ë¼ ì»¤ë°‹ëœ íŠ¸ëžœìžì…˜ì˜ ì¼ë¶€ë¥¼ ìžë™ì 으로 롤백한다. 예를 들어 **COMMIT WORK** ë¬¸ì´ ìˆ˜í–‰ë˜ëŠ” ë™ì•ˆ ë°œìƒí•œ 시스템 오류는 트랜ìžì…˜ì´ ì•„ì§ ì»¤ë°‹ë˜ì§€ 않았다면(사용ìžì˜ ì—°ì‚°ì´ ì»¤ë°‹ë˜ì—ˆë‹¤ëŠ” 확ì¸ì„ 받지 못한다) 중단해야 í• ê²ƒì´ë‹¤. ìžë™ ì¤‘ë‹¨ì€ ì»¤ë°‹ë˜ì§€ ì•Šì€ ê°±ì‹ ì„ ì·¨ì†Œí•¨ìœ¼ë¡œì¨ ë°ì´í„°ë² ì´ìŠ¤ì— ì›í•˜ì§€ ì•Šì€ ë³€ê²½ì„ ì•¼ê¸°í•˜ëŠ” 오류를 방지한다. ë°ì´í„°ë² ì´ìФ ìž¬êµ¬ë™ ------------------- CUBRID는 시스템과 매체(디스í¬)ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆì„ 때 커밋ë˜ì—ˆê±°ë‚˜ 커밋ë˜ì§€ ì•Šì€ íŠ¸ëžœìžì…˜ì„ 복구하기 위해 로그 볼륨/파ì¼ê³¼ ë°ì´í„°ë² ì´ìФ ë°±ì—…ì„ ì´ìš©í•œë‹¤. 로그는 사용ìžê°€ ì§€ì •í•œ ë¡¤ë°±ì„ ì§€ì›í•˜ëŠ”ë°ë„ 사용ëœë‹¤. 로그는 CUBRIDê°€ ìƒì„±í•œ 순차ì ì¸ íŒŒì¼ì˜ 모ìŒìœ¼ë¡œ 구성ëœë‹¤. 가장 ìµœê·¼ì˜ ë¡œê·¸ë¥¼ 활성 로그(active log)ë¼ê³ 부르며, 나머지 로그를 ë³´ê´€ 로그(archive log)ë¼ê³ 부른다. 로그 파ì¼ì€ 활성 로그와 ë³´ê´€ 로그 ì „ì²´ë¥¼ ê°€ë¦¬í‚¤ëŠ”ë° ì‚¬ìš©ëœë‹¤. ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•œ ëª¨ë“ ê°±ì‹ ì€ ë¡œê·¸ì— ê¸°ë¡ëœë‹¤. ì‹¤ì œë¡œ ê°±ì‹ ì— ëŒ€í•œ 2ê°œì˜ ë³µì‚¬ë³¸ì´ ê¸°ë¡ë˜ëŠ”ë°, 첫 번째 ë³µì‚¬ë³¸ì€ before ì´ë¯¸ì§€(UNDO log)ë¼ê³ 불리며 사용ìžê°€ 명시한 **ROLLBACK WORK** ë¬¸ì´ ìˆ˜í–‰ë˜ëŠ” ë™ì•ˆì´ë‚˜ 매체 ë˜ëŠ” ì‹œìŠ¤í…œì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆì„ 때 ë°ì´í„°ë¥¼ ë³µì›í•˜ëŠ”ë° ì‚¬ìš©ëœë‹¤. ë‘ ë²ˆì§¸ ë³µì‚¬ë³¸ì€ after ì´ë¯¸ì§€(REDO log)ì¸ë° 매체 ë˜ëŠ” ì‹œìŠ¤í…œì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆì„ 때 ê°±ì‹ ì„ ë‹¤ì‹œ ì ìš©ì‹œí‚¤ëŠ”ë° ì‚¬ìš©ëœë‹¤. CUBRID는 활성 로그가 꽉 차면 ë³´ê´€ 로그로 복사하여 디스í¬ì— 보존한다. ë³´ê´€ 로그는 시스템 ìž¥ì• ê°€ ë°œìƒí–ˆì„ 때 ë°ì´í„°ë² ì´ìФ 복구를 위해 필요하다. **ì •ìƒì ì¸ ì¢…ë£Œ ë˜ëŠ” 오류** ë°ì´í„°ë² ì´ìŠ¤ê°€ ì •ìƒì ì¸ ì¢…ë£Œë‚˜ ìž¥ë¹„ì˜ ì˜¤ë¥˜ë¡œ 다시 시작ë˜ë©´ CUBRID는 ìžë™ì 으로 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 복구한다. 복구 프로세스는 ë°ì´í„°ë² ì´ìŠ¤ì— ë¹ ì ¸ìžˆëŠ” ì»¤ë°‹ëœ ë³€í™”ë¥¼ 다시 ì ìš©í•˜ê³ ë°ì´í„°ë² ì´ìŠ¤ì— ì €ìž¥ë˜ì–´ 있는 커밋ë˜ì§€ ì•Šì€ ë³€ê²½ì„ ì œê±°í•œë‹¤. ë°ì´í„°ë² ì´ìФ ì‹œìŠ¤í…œì˜ ì¼ë°˜ì ì¸ ì—°ì‚°ì€ ë³µêµ¬ê°€ ëë‚˜ê³ ë‚œ 후 재개ëœë‹¤. ì´ëŸ¬í•œ 복구 프로세스는 ì–´ë– í•œ ë³´ê´€ 로그나 ë°ì´í„°ë² ì´ìФ ë°±ì—…ë„ ì‚¬ìš©í•˜ì§€ 않는다. ë°ì´í„°ë² ì´ìŠ¤ëŠ” **cubrid server** ìœ í‹¸ë¦¬í‹°ë¥¼ ì´ìš©í•´ 재구ë™í• 수 있다. **매체 오류** ë§¤ì²´ì— ì˜¤ë¥˜ê°€ ë°œìƒ í•œ í›„ì— ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 다시 구ë™ì‹œí‚¤ëŠ” ë°ëŠ” 사용ìžì˜ ê°œìž…ì´ ë‹¤ì†Œ 필요하다. 첫 번째 단계는 ì¢‹ì€ ìƒíƒœë¡œ ì•Œë ¤ì§„ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë°±ì—…ì„ ì„¤ì¹˜í•˜ì—¬ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë³µì›í•˜ëŠ” 것ì´ë‹¤. CUBRIDì—서 가장 ìµœê·¼ì˜ ë¡œê·¸ 파ì¼(마지막 백업 ì´í›„ì˜ ê²ƒ)ì„ ì„¤ì¹˜í•˜ëŠ” ê²ƒì„ í•„ìš”ë¡œ 한다. ì´ íŠ¹ì • 로그(ë³´ê´€, 활성)는 ë°ì´í„°ë² ì´ìŠ¤ì˜ ë°±ì—… ë³µì‚¬ë³¸ì— ì ìš©ëœë‹¤. ë³µì›ì´ ì»¤ë°‹ëœ í›„ ë°ì´í„°ë² ì´ìŠ¤ëŠ” ì¼ë°˜ì ì¸ ì¢…ë£Œì˜ ê²½ìš°ì™€ 마찬가지로 재구ë™í• 수 있다. .. note:: ë°ì´í„°ë² ì´ìŠ¤ì˜ ì •ë³´ë¥¼ 잃어버릴 ê°€ëŠ¥ì„±ì„ ì¤„ì´ê¸° 위해서 ë³´ê´€ 로그가 디스í¬ì—서 ì‚ì œë˜ê¸° ì „ì— ë³´ê´€ ë¡œê·¸ì˜ ìŠ¤ëƒ…ìƒ·ì„ ë§Œë“¤ê³ ì´ë¥¼ 백업 ìž¥ì¹˜ì— ë³´ê´€í• ê²ƒì„ ê¶Œìž¥í•œë‹¤. DBA는 **cubrid backupdb**, **cubrid restoredb** ìœ í‹¸ë¦¬í‹°ë¥¼ 사용하여 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë°±ì—…í•˜ê³ ë³µì›í• 수 있다. ì´ ìœ í‹¸ë¦¬í‹°ì— ëŒ€í•œ ìƒì„¸í•œ ë‚´ìš©ì„ ë³´ë ¤ë©´ :ref:`backupdb`\를 ì°¸ê³ í•œë‹¤.