************ CUBRID SHARD ************ Database Sharding ================= **ìˆ˜í‰ ë¶„í• ** ìˆ˜í‰ ë¶„í• (horizontal partitioning)ì´ëž€ 스키마가 ë™ì¼í•œ ë°ì´í„°ë¥¼ í–‰ì„ ê¸°ì¤€ìœ¼ë¡œ ë‘ ê°œ ì´ìƒì˜ í…Œì´ë¸”ì— ë‚˜ëˆ„ì–´ ì €ìž¥í•˜ëŠ” ë””ìžì¸ì„ ë§í•œë‹¤. 예를 들어 'User Table'ì„ ë™ì¼ ìŠ¤í‚¤ë§ˆì˜ 13세 ë¯¸ë§Œì˜ ìœ ì €ë¥¼ ì €ìž¥í•˜ëŠ” 'User Table #0'ê³¼ 13세 ì´ìƒì˜ ìœ ì €ë¥¼ ì €ìž¥í•˜ëŠ” 'User Table #1'로 ë¶„í• í•˜ì—¬ ì‚¬ìš©í• ìˆ˜ 있다. ìˆ˜í‰ ë¶„í• ë¡œ ì¸í•´ ê° í…Œì´ë¸”ì˜ ë°ì´í„°ì™€ ì¸ë±ìŠ¤ì˜ í¬ê¸°ê°€ ê°ì†Œí•˜ê³ 작업 ë™ì‹œì„±ì´ 늘어 성능 í–¥ìƒì„ ê¸°ëŒ€í• ìˆ˜ 있다. ìˆ˜í‰ ë¶„í• ì€ ì¼ë°˜ì 으로 í•˜ë‚˜ì˜ í…Œì´í„°ë² ì´ìФ 안ì—서 ì´ë£¨ì–´ì§„다. ìˆ˜í‰ ë¶„í• ë¡œ ì¸í•´ ê° í…Œì´ë¸”ì˜ ë°ì´í„°ì™€ ì¸ë±ìŠ¤ì˜ í¬ê¸°ê°€ ê°ì†Œí•˜ê¸° ë•Œë¬¸ì— ì„±ëŠ¥ í–¥ìƒì„ ê¸°ëŒ€í• ìˆ˜ 있다. .. image:: /images/image38.png **database sharding** database shardingì€ ë¬¼ë¦¬ì 으로 다른 ë°ì´í„°ë² ì´ìŠ¤ì— ë°ì´í„°ë¥¼ ìˆ˜í‰ ë¶„í• (horizontal partitioning) ë°©ì‹ìœ¼ë¡œ ë¶„ì‚° ì €ìž¥í•˜ê³ ì¡°íšŒí•˜ëŠ” ë°©ë²•ì„ ë§í•œë‹¤. 예를 들어 'User Table'ì´ ì—¬ëŸ¬ ë°ì´í„°ë² ì´ìŠ¤ì— ìžˆì„ ë•Œ 13세 ë¯¸ë§Œì˜ ìœ ì €ë¥¼ 0번 ë°ì´í„°ë² ì´ìŠ¤ì— 13세 ì´ìƒì˜ ìœ ì €ë¥¼ 1번 ë°ì´í„°ë² ì´ìŠ¤ì— ì €ìž¥ë˜ë„ë¡ í•˜ëŠ” ë°©ì‹ì´ë‹¤. database shardingì€ ì„±ëŠ¥ìƒ ì´ìœ ë¿ ì•„ë‹ˆë¼ í•˜ë‚˜ì˜ ë°ì´í„°ë² ì´ìФ ì¸ìŠ¤í„´ìŠ¤ì— ë„£ì„ ìˆ˜ 없는 í° ë°ì´í„°ë¥¼ 분산하여 처리하기 위해 사용ëœë‹¤. ë¶„í• ëœ ê° ë°ì´í„°ë² ì´ìŠ¤ë¥¼ shard ë˜ëŠ” database shardë¼ê³ 부른다. .. image:: /images/image39.png **CUBRID SHARD** CUBRID SHARD는 database shardingì„ ìœ„í•œ 미들웨어로, 다ìŒê³¼ ê°™ì€ íŠ¹ì§•ì„ ê°–ëŠ”ë‹¤. * 기존 ì‘ìš©ì˜ ë³€ê²½ì„ ìµœì†Œí™”í•˜ê¸° 위한 미들웨어 형태로서, í”히 사용ë˜ëŠ” JDBC(Java Database Connectivity)나 CUBRID C APIì¸ CCI(CUBRID C Interface)를 ì´ìš©í•˜ì—¬ 투명하게 shardingëœ ë°ì´í„°ì— ì ‘ê·¼í• ìˆ˜ 있다. * 힌트를 ì´ìš©í•˜ì—¬ ì‹¤ì œ ì§ˆì˜ ìˆ˜í–‰í• shard를 ì„ íƒí•˜ëŠ” ë°©ì‹ìœ¼ë¡œ, 기존 ì‚¬ìš©í•˜ë˜ ì§ˆì˜ì— 힌트를 추가하여 ì‚¬ìš©í• ìˆ˜ 있다. * ì¼ë¶€ 트랜ìžì…˜ì˜ íŠ¹ì„±ì„ ë³´ìž¥í•œë‹¤. .. _shard-terminologies: CUBRID SHARD 기본 용어 ====================== 다ìŒì€ 앞으로 CUBRID SHARD를 설명하기 위해 사용ë˜ëŠ” 용어들로, ê° ì˜ë¯¸ëŠ” 다ìŒê³¼ 같다. * **shard DB** : ë¶„í• ëœ í…Œì´ë¸”ê³¼ ë°ì´í„°ë¥¼ í¬í•¨í•˜ê³ 있으며, ì‹¤ì œë¡œ ì‚¬ìš©ìž ìš”ì²ì„ 처리하는 ë°ì´í„°ë² ì´ìФ * **shard metadata** : CUBRID SHARDì˜ ë™ìž‘ì„ ìœ„í•œ ì„¤ì • ì •ë³´. ìš”ì²ëœ 질ì˜ë¥¼ ë¶„ì„하여 ì‹¤ì œ 질ì˜ë¥¼ ìˆ˜í–‰í• shard DB를 ì„ íƒí•˜ê¸° 위한 ì •ë³´ ë° shard DBì™€ì˜ ë°ì´í„°ë² ì´ìФ ì„¸ì…˜ì„ ìƒì„±í•˜ê¸° 위한 ì •ë³´ë¥¼ í¬í•¨í•œë‹¤. * **shard key (column)** : shardingëœ í…Œì´ë¸”ì—서 shard를 ì„ íƒí•˜ê¸° 위한 ì‹ë³„ìžë¡œ 사용ë˜ëŠ” 칼럼 * **shard key data** : ì§ˆì˜ ì¤‘ shard를 ì‹ë³„하기 위한 ížŒíŠ¸ì— í•´ë‹¹í•˜ëŠ” shard keyì˜ ê°’ * **shard ID** : shard DB를 ì‹ë³„하기 위한 ì‹ë³„ìž * **proxy** : ì‚¬ìš©ìž ì§ˆì˜ì— í¬í•¨ëœ 힌트를 í•´ì„í•˜ê³ , í•´ì„ëœ ížŒíŠ¸ì™€ shard metadata를 ì´ìš©í•˜ì—¬ ì‹¤ì œ ì§ˆì˜ ì²˜ë¦¬í• shard DB로 ìš”ì²ì„ ì „ë‹¬í•˜ëŠ” ì—í• ì„ í•˜ëŠ” CUBRID 미들웨어 프로세스 CUBRID SHARD 주요 기능 ====================== 미들웨어 구조 ------------- CUBRID SHARD는 ì‘ìš© 프로그램과 물리ì ë˜ëŠ” 논리ì 으로 ë¶„í• ëœ shardì˜ ì¤‘ê°„ì— ìœ„ì¹˜í•˜ëŠ” 미들웨어(middleware)로서, ë™ì‹œì— ë‹¤ìˆ˜ì˜ ì‘ìš© í”„ë¡œê·¸ëž¨ê³¼ì˜ ì—°ê²°ì„ ìœ ì§€í•˜ë©°, ì‘ìš©ì˜ ìš”ì²ì´ 있는 경우 ì ì ˆí•œ shard로 ì „ë‹¬í•˜ì—¬ ì²˜ë¦¬í•˜ê³ ê²°ê³¼ë¥¼ ì‘ìš©ì— ë°˜í™˜í•˜ëŠ” ê¸°ëŠ¥ì„ ìˆ˜í–‰í•œë‹¤. .. image:: /images/image40.png ì¼ë°˜ì 으로 사용ë˜ëŠ” JDBC(Java Database Connectivity)나 CUBRID C ì¸í„°íŽ˜ì´ìŠ¤ì¸ CCI(CUBRID C Interface)를 ì´ìš©í•˜ì—¬ CUBRID SHARD로 연결하여 ì‘ìš©ì˜ ìš”ì²ì„ ì²˜ë¦¬í• ìˆ˜ 있으며, 별ë„ì˜ ë“œë¼ì´ë²„나 í”„ë ˆìž„ì›Œí¬ê°€ í•„ìš” 없기 ë•Œë¬¸ì— ê¸°ì¡´ ì‘ìš©ì˜ ë³€ê²½ì„ ìµœì†Œí™”í• ìˆ˜ 있다. CUBRID SHARD middleware는 broker/proxy/CAS 세 ê°œì˜ í”„ë¡œì„¸ìŠ¤ë¡œ 구성ë˜ë©°, ê° í”„ë¡œì„¸ìŠ¤ì˜ ê°„ëžµí•œ ê¸°ëŠ¥ì€ ë‹¤ìŒê³¼ 같다. .. image:: /images/image41.png * **broker** * JDBC/CCI 등 드ë¼ì´ë²„ë¡œë¶€í„°ì˜ ìµœì´ˆ ì—°ê²° ìš”ì²ì„ ìˆ˜ì‹ í•˜ê³ , ìˆ˜ì‹ ëœ ì—°ê²° ìš”ì²ì„ 부하 ë¶„ì‚° ì •ì±…ì— ë”°ë¼ proxy로 ì „ë‹¬ * proxy 프로세스와 CAS í”„ë¡œì„¸ìŠ¤ì˜ ìƒíƒœ ê°ì‹œ ë° ë³µêµ¬ * **proxy** * 드ë¼ì´ë²„ë¡œë¶€í„°ì˜ ì‚¬ìš©ìž ìš”ì²ì„ CAS로 ì „ë‹¬í•˜ê³ , 처리한 결과를 ì‘ìš©ì— ë°˜í™˜ * 드ë¼ì´ë²„ ë° CASì™€ì˜ ì—°ê²° ìƒíƒœ 관리 ë° íŠ¸ëžœìžì…˜ 처리 * **CAS** * ë¶„í• ëœ shard DB와 ì—°ê²°ì„ ìƒì„±í•˜ê³ , ê·¸ ì—°ê²°ì„ ì´ìš©í•˜ì—¬ proxy로부터 ìˆ˜ì‹ í•œ ì‚¬ìš©ìž ìš”ì²(질ì˜)를 처리 * 트랜ìžì…˜ 처리 shard SQL 힌트를 ì´ìš©í•œ shard DB ì„ íƒ ------------------------------------- **shard SQL 힌트** CUBRID SHARD는 SQL 힌트 êµ¬ë¬¸ì— í¬í•¨ëœ 힌트와 ì„¤ì • ì •ë³´ë¥¼ ì´ìš©í•˜ì—¬, ì‘용으로부터 ìš”ì²ëœ 질ì˜ë¥¼ ì‹¤ì œë¡œ ì²˜ë¦¬í• shard DB를 ì„ íƒí•œë‹¤. 사용 가능한 SQL ížŒíŠ¸ì˜ ì¢…ë¥˜ëŠ” 다ìŒê³¼ 같다. +----------------------+----------------------------------------------------------------------------------+ | SQL 힌트 | 설명 | +======================+==================================================================================+ | **/*+ shard_key */** | shard key ì¹¼ëŸ¼ì— í•´ë‹¹í•˜ëŠ” ë°”ì¸ë“œ 변수 ë˜ëŠ” 리터럴 ê°’ì˜ ìœ„ì¹˜ë¥¼ ì§€ì •í•˜ê¸° 위한 힌트 | +----------------------+----------------------------------------------------------------------------------+ | **/*+ shard_val(** | ì§ˆì˜ ë‚´ì— shard keyì— í•´ë‹¹í•˜ëŠ” ì¹¼ëŸ¼ì´ ì¡´ìž¬í•˜ì§€ 않는 경우 힌트 ë‚´ì— | | *value* | shard key를 명시ì 으로 ì§€ì •í•˜ê¸° 위한 힌트 | | **) */** | | +----------------------+----------------------------------------------------------------------------------+ | **/*+ shard_id(** | 사용ìžê°€ íŠ¹ì • shard DB를 ì§€ì •í•˜ì—¬ 질ì˜ë¥¼ ì²˜ë¦¬í•˜ê³ ìž í• ë•Œ 사용하는 | | *shard_id* | 힌트 | | **) */** | | +----------------------+----------------------------------------------------------------------------------+ ì„¤ëª…ì„ ìœ„í•´ 간략하게 용어를 ì •ë¦¬í•˜ë©´ 다ìŒê³¼ 같다. ìš©ì–´ì— ëŒ€í•œ 보다 ìžì„¸í•œ ì„¤ëª…ì€ :ref:`shard-terminologies`\ 를 ì°¸ê³ í•œë‹¤. * **shard key** : shard DB를 ì‹ë³„í• ìˆ˜ 있는 칼럼. ì¼ë°˜ì 으로 shard DB ë‚´ì˜ ëª¨ë“ í˜¹ì€ ëŒ€ë¶€ë¶„ì˜ í…Œì´ë¸”ì— ì¡´ìž¬í•˜ëŠ” 칼럼으로서, DB ë‚´ì—서 ìœ ì¼í•œ ê°’ì„ ê°–ëŠ”ë‹¤. * **shard id** : shard를 논리ì 으로 êµ¬ë¶„í• ìˆ˜ 있는 ì‹ë³„ìž. 예를 들어, í•˜ë‚˜ì˜ DBê°€ 4ê°œì˜ shard DB로 ë¶„í• ë˜ë©´ 4ê°œì˜ shard idê°€ 존재한다. 힌트와 ì„¤ì • ì •ë³´ë¥¼ ì´ìš©í•œ ìžì„¸í•œ ì§ˆì˜ ì²˜ë¦¬ ì ˆì°¨ëŠ” :ref:`shard SQL 힌트를 ì´ìš©í•˜ì—¬ 질ì˜ê°€ 수행ë˜ëŠ” ì¼ë°˜ì ì¸ ì ˆì°¨ <using-shard-hint>`\ 를 ì°¸ê³ í•œë‹¤. .. note:: * í•˜ë‚˜ì˜ ì§ˆì˜ ì•ˆì— ë‘ ê°œ ì´ìƒì˜ shard 힌트가 ì¡´ìž¬í• ê²½ìš° 서로 ê°™ì€ shard를 가리키면 ì •ìƒ ì²˜ë¦¬í•˜ê³ , 다른 shard를 가리키면 오류 처리한다. :: SELECT * FROM student WHERE shard_key = /*+ shard_key */ 250 OR shard_key = /*+ shard_key */ 22; 위와 ê°™ì€ ê²½ìš° 250ê³¼ 22ê°€ ê°™ì€ shard를 가리키면 ì •ìƒ ì²˜ë¦¬, 다른 shard를 가리키면 오류 처리한다. * 여러 ê°œì˜ ê°’ì„ ë°”ì¸ë”©í•˜ëŠ” 배열로 질ì˜ë¥¼ ì¼ê´„ 처리하는 드ë¼ì´ë²„ 함수(예: JDBCì˜ PreparedStatement.executeBatch, CCIì˜ cci_execute_array)ì—서 여러 ê°œì˜ ì§ˆì˜ ì¤‘ 하나ë¼ë„ 다른 shardì— ì ‘ê·¼í•˜ëŠ” 질ì˜ê°€ 있으면 ëª¨ë‘ ì˜¤ë¥˜ 처리한다. * shard 환경ì—서 í•œë²ˆì— ì—¬ëŸ¬ ë¬¸ìž¥ì„ ì‹¤í–‰í•˜ëŠ” 함수(예: JDBCì˜ Statement.executeBatch, CCIì˜ cci_execute_batch)는 추후 ì§€ì›í• ì˜ˆì •ì´ë‹¤. **shard_key 힌트** **shard_key** 힌트는 ë°”ì¸ë“œ 변수나 리터럴 ê°’ì˜ ìœ„ì¹˜ë¥¼ ì§€ì •í•˜ê¸° 위한 힌트로서, 반드시 ë°”ì¸ë“œ 변수나 리터럴 ê°’ì˜ ì•žì— ìœ„ì¹˜í•´ì•¼ 한다. 예) ë°”ì¸ë“œ 변수 위치 ì§€ì •. 실행 시 ë°”ì¸ë”©ë˜ëŠ” student_no ê°’ì— í•´ë‹¹í•˜ëŠ” shard DBì—서 질ì˜ë¥¼ 수행. .. code-block:: sql SELECT name FROM student WHERE student_no = /*+ shard_key */ ?; 예) 리터럴 ê°’ 위치 ì§€ì •. 실행 시 리터럴 ê°’ì¸ student_noê°€ 123ì— í•´ë‹¹í•˜ëŠ” shard DBì—서 질ì˜ë¥¼ 수행 .. code-block:: sql SELECT name FROM student WHERE student_no = /*+ shard_key */ 123; **shard_val 힌트** **shard_val** 힌트는 ì§ˆì˜ ë‚´ì— shard DB를 ì‹ë³„í• ìˆ˜ 있는 shard key ì¹¼ëŸ¼ì´ ì¡´ìž¬í•˜ì§€ 않는 경우 사용하며, ì‹¤ì œ ì§ˆì˜ ì²˜ë¦¬ 시 무시ë˜ëŠ” shard key ì¹¼ëŸ¼ì„ **shard_val** ížŒíŠ¸ì˜ ê°’ìœ¼ë¡œ ì„¤ì •í•œë‹¤. **shard_val** 힌트는 SQL êµ¬ë¬¸ì˜ ì–´ëŠ ê³³ì—나 ìœ„ì¹˜í• ìˆ˜ 있다. 예) shard keyê°€ student_noì´ë‚˜ ì§ˆì˜ ë‚´ì— í¬í•¨ë˜ì§€ ì•Šì€ ê²½ìš°. shard keyì¸ student_noê°€ 123ì— í•´ë‹¹í•˜ëŠ” shard DBì—서 질ì˜ë¥¼ 수행 .. code-block:: sql SELECT age FROM student WHERE name =? /*+ shard_val(123) */; **shard_id 힌트** **shard_id** 힌트는 shard key ì¹¼ëŸ¼ì˜ ê°’ê³¼ 무관하게 사용ìžê°€ íŠ¹ì • shard를 ì§€ì •í•˜ì—¬ 질ì˜ë¥¼ ìˆ˜í–‰í•˜ê³ ìž í• ë•Œ 사용한다. **shard_id** 힌트는 SQL êµ¬ë¬¸ì˜ ì–´ëŠ ê³³ì—나 ìœ„ì¹˜í• ìˆ˜ 있다. 예) shard DB #3 ì—서 질ì˜ë¥¼ 수행해야 하는 경우. shard DB #3ì—서 ageê°€ 17보다 í° í•™ìƒì„ 조회 .. code-block:: sql SELECT * FROM student WHERE age > 17 /*+ shard_id(3) */; .. _using-shard-hint: **shard SQL 힌트를 ì´ìš©í•˜ì—¬ 질ì˜ê°€ 수행ë˜ëŠ” ì¼ë°˜ì ì¸ ì ˆì°¨** #. ì§ˆì˜ ìˆ˜í–‰ 다ìŒì€ ì‚¬ìš©ìž ì§ˆì˜ ìš”ì²ì´ 수행ë˜ëŠ” ê³¼ì •ì´ë‹¤. .. image:: /images/image42.png * ì‘ìš© í”„ë¡œê·¸ëž¨ì€ JDBC ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 통해 CUBRID SHARD로 ì§ˆì˜ ì²˜ë¦¬ë¥¼ ìš”ì²í•˜ë©°, ì‹¤ì œë¡œ 질ì˜ê°€ 수행ë shard DB를 ì§€ì •í•˜ê¸° 위해 SQL 구문 ë‚´ì— **shard_key** 힌트를 추가한다. * SQL 힌트는 SQL 구문 ë‚´ì—서 위 예ì—서와 마찬가지로 shard key로 ì„¤ì •ëœ ì¹¼ëŸ¼ì˜ ë°”ì¸ë“œ ë˜ëŠ” 리터럴 ê°’ 바로 ì•žì— ìœ„ì¹˜í•´ì•¼ 한다. ë°”ì¸ë“œ ë³€ìˆ˜ì— ì„¤ì •ëœ shard SQL 힌트는 다ìŒê³¼ 같다. .. image:: /images/image43.png 리터럴 ê°’ì— ì§€ì •ëœ shard SQL 힌트는 다ìŒê³¼ 같다. .. image:: /images/image44.png #. ì§ˆì˜ ë¶„ì„ ë° ì‹¤ì œ ìš”ì²ì„ ì²˜ë¦¬í• shard DB ì„ íƒ ì§ˆì˜ë¥¼ ë¶„ì„í•˜ê³ ì‹¤ì œë¡œ ìš”ì²ì„ ì²˜ë¦¬í• shard DB를 ì„ íƒí•˜ëŠ” ê³¼ì •ì€ ë‹¤ìŒê³¼ 같다. .. image:: /images/image45.png * 사용ìžë¡œë¶€í„° ìˆ˜ì‹ í•œ SQL 질ì˜ë¥¼ ë‚´ë¶€ì—서 처리하기 위한 형태로 다시 작성ëœë‹¤(query rewrite). * 사용ìžê°€ ìš”ì²í•œ SQL 구문과 힌트를 ì´ìš©í•˜ì—¬ ì‹¤ì œ 질ì˜ë¥¼ 수행한 shard DB를 ì„ íƒí•œë‹¤. * ë°”ì¸ë“œ ë³€ìˆ˜ì— SQL 힌트가 ì„¤ì •ëœ ê²½ìš°, execute 시 shard_key ë°”ì¸ë“œ ë³€ìˆ˜ì— ëŒ€ìž…ëœ ê°’ì„ í•´ì‹œí•œ 결과와 ì„¤ì • ì •ë³´ë¥¼ ì´ìš©í•˜ì—¬ ì‹¤ì œ 질ì˜ê°€ 수행ë shard DB를 ì„ íƒí•œë‹¤. * 해시 함수는 사용ìžê°€ 별ë„로 ì§€ì •í• ìˆ˜ 있으며, ì§€ì •í•˜ì§€ ì•Šì€ ê²½ìš° 기본 ë‚´ìž¥ëœ í•´ì‹œ 함수를 ì´ìš©í•˜ì—¬ shard_key ê°’ì„ í•´ì‹±í•œë‹¤. 기본 ë‚´ìž¥ëœ í•´ì‹œ 함수는 다ìŒê³¼ 같다. * shard_keyê°€ ì •ìˆ˜ì¸ ê²½ìš° :: 기본 해시 함수(shard_key) = shard_key mod SHARD_KEY_MODULAR 파ë¼ë¯¸í„°(기본값 256) * shard_keyê°€ 문ìžì—´ì¸ 경우 :: 기본 해시 함수(shard_key) = shard_key[0] mod SHARD_KEY_MODULAR 파ë¼ë¯¸í„°(기본값 256) .. note:: shard_key ë°”ì¸ë“œ ë³€ìˆ˜ì˜ ê°’ì´ 100ì¸ ê²½ìš°, "기본 hash 함수(shard_key) = 100 % 256 = 100"ì´ë¯€ë¡œ, ì„¤ì •ì— ì˜í•´ 해시 ê²°ê³¼ 100ì— í•´ë‹¹í•˜ëŠ” shard DB #1ì´ ì„ íƒë˜ë©°, ì„ íƒëœ shard DB #1으로 ì‚¬ìš©ìž ìš”ì²ì„ ì „ë‹¬í•˜ê²Œ ëœë‹¤. #. ì§ˆì˜ ìˆ˜í–‰ ê²°ê³¼ 반환 ì§ˆì˜ ìˆ˜í–‰ 결과를 반환하는 ê³¼ì •ì€ ë‹¤ìŒê³¼ 같다. .. image:: /images/image46.png * shard DB #1 ì—서 수행한 처리 결과를 ìˆ˜ì‹ í•˜ì—¬, ìš”ì²í•œ ì‘용으로 결과를 반환한다. .. note:: 여러 ê°œì˜ ê°’ì„ ë°”ì¸ë”©í•˜ëŠ” 배열로 질ì˜ë¥¼ ì¼ê´„ 처리하는 드ë¼ì´ë²„ 함수(예: JDBCì˜ executeBatch, CCIì˜ cci_execute_array, cci_execute_batch)ì—서 다른 shardì— ì ‘ê·¼í•˜ëŠ” ê°’ì´ ì¡´ìž¬í•˜ë©´ 오류 처리한다. 트랜ìžì…˜ ì§€ì› ------------- **트랜ìžì…˜ 처리** CUBRID SHARD는 ACID 중 Atomicity(ì›ìžì„±)ì„ ë³´ìž¥í•˜ê¸° 위한 ë‚´ë¶€ì ì¸ ì²˜ë¦¬ ì ˆì°¨ë¥¼ 수행한다. 예를 들어, 트랜ìžì…˜ 중 ì‘ìš©ì´ ë¹„ì •ìƒ ì¢…ë£Œí•˜ëŠ” ë“±ì˜ ì˜ˆì™¸ê°€ ë°œìƒí•˜ë©´ 해당 ì‘ìš©ì˜ ì§ˆì˜ë¥¼ ì²˜ë¦¬í•˜ë˜ shard DB로 롤백 ìš”ì²ì„ ì „ë‹¬í•˜ì—¬ 해당 트랜ìžì…˜ 중 ë³€ê²½ëœ ë‚´ìš©ì„ ëª¨ë‘ ë¬´íš¨í™”í•œë‹¤. ê·¸ 외 ì¼ë°˜ì ì¸ íŠ¸ëžœìžì…˜ì˜ íŠ¹ì„±ì¸ ACID는 backend DBMSì˜ íŠ¹ì„±ê³¼ ì„¤ì •ì— ë”°ë¼ ë³´ìž¥ëœë‹¤. **ì œì•½ 사í•** 2PC(2 Phase commit)는 불가능하며, ì´ ë•Œë¬¸ì— í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ 중 여러 ê°œì˜ shard DB로 질ì˜ë¥¼ 수행하는 경우 ì—러 처리ëœë‹¤. ë¹ ë¥¸ 시작 ========= 구성 예 ------- 예로 설명ë CUBRID SHARD는 아래 그림과 ê°™ì´ 4ê°œì˜ CUBRID SHARD DB로 구성ë˜ì—ˆìœ¼ë©°, ì‘ìš©ì€ JDBC ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 사용하여 ì‚¬ìš©ìž ìš”ì²ì„ 처리한다. .. image:: /images/image49.png **shard DB ë° ì‚¬ìš©ìž ê³„ì • ìƒì„± 후 시작** 위 êµ¬ì„±ì˜ ì˜ˆì™€ ê°™ì´ ê° shard DB 노드ì—서 shard DB ë° ì‚¬ìš©ìž ê³„ì •ì„ ìƒì„±í•œ 후 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì¸ìŠ¤í„´ìŠ¤ë¥¼ 시작한다. * shard DB ì´ë¦„ : *shard1* * shard DB ì‚¬ìš©ìž ê³„ì • : *shard* * shard DB ì‚¬ìš©ìž ë¹„ë°€ë²ˆí˜¸ : *shard123* :: sh> # CUBRID SHARD DB ìƒì„± sh> cubrid createdb shard1 en_US sh> # CUBRID SHARD ì‚¬ìš©ìž ê³„ì • ìƒì„± sh> csql -S -u dba shard1 -c "create user shard password 'shard123'" sh> # CUBRID SHARD DB 시작 sh> cubrid server start shard1 shard ì„¤ì • 변경 --------------- **cubrid_broker.conf** **cubrid_broker.conf.shard**\ 를 참조하여 **cubrid_broker.conf**\ 를 아래와 ê°™ì´ ë³€ê²½í•œë‹¤. .. warning:: í¬íЏ 번호 ë° ê³µìœ ë©”ëª¨ë¦¬ ì‹ë³„ìžëŠ” 현재 시스템ì—서 사용하지 않는 값으로 ì ì ˆížˆ 변경해야 한다. :: [broker] MASTER_SHM_ID =30001 ADMIN_LOG_FILE =log/broker/cubrid_broker.log [%shard1] SERVICE =ON BROKER_PORT =36000 MIN_NUM_APPL_SERVER =20 MAX_NUM_APPL_SERVER =40 APPL_SERVER_SHM_ID =36000 LOG_DIR =log/broker/sql_log ERROR_LOG_DIR =log/broker/error_log SQL_LOG =ON TIME_TO_KILL =120 SESSION_TIMEOUT =300 KEEP_CONNECTION =ON MAX_PREPARED_STMT_COUNT =1024 SHARD =ON SHARD_DB_NAME =shard1 SHARD_DB_USER =shard SHARD_DB_PASSWORD =shard123 SHARD_NUM_PROXY =1 SHARD_PROXY_LOG_DIR =log/broker/proxy_log SHARD_PROXY_LOG =ERROR SHARD_MAX_CLIENTS =256 SHARD_PROXY_SHM_ID =36090 SHARD_CONNECTION_FILE =shard_connection.txt SHARD_KEY_FILE =shard_key.txt CUBRIDì˜ ê²½ìš° **shard_connection.txt**\ ì— ì„œë²„ì˜ í¬íЏ 번호를 별ë„로 ì„¤ì •í•˜ì§€ ì•Šê³ **cubrid.conf** ì„¤ì • 파ì¼ì˜ **cubrid_port_id** 파ë¼ë¯¸í„°ë¥¼ 사용하므로, **cubrid.conf** ì˜ **cubrid_port_id** 파ë¼ë¯¸í„°ë¥¼ 서버와 ë™ì¼í•˜ê²Œ ì„¤ì •í•œë‹¤. :: # TCP port id for the CUBRID programs (used by all clients). cubrid_port_id=41523 **shard_key.txt** shard key 해시 ê°’ì— ëŒ€í•œ shard DB 매핑 ì„¤ì • 파ì¼ì¸ **shard_key.txt** 파ì¼ì„ 아래와 ê°™ì´ ì„¤ì •í•œë‹¤. * [%shard_key] : shard key 섹션 ì„¤ì • * 기본 해시 í•¨ìˆ˜ì— ì˜í•œ shard key 해시 결과가 0~63ì¸ ê²½ìš° shard #0 ì—서 ì§ˆì˜ ìˆ˜í–‰ * 기본 해시 í•¨ìˆ˜ì— ì˜í•œ shard key 해시 결과가 64~127ì¸ ê²½ìš° shard #1 ì—서 ì§ˆì˜ ìˆ˜í–‰ * 기본 해시 í•¨ìˆ˜ì— ì˜í•œ shard key 해시 결과가 128~191ì¸ ê²½ìš° shard #2 ì—서 ì§ˆì˜ ìˆ˜í–‰ * 기본 해시 í•¨ìˆ˜ì— ì˜í•œ shard key 해시 결과가 192~255ì¸ ê²½ìš° shard #3 ì—서 ì§ˆì˜ ìˆ˜í–‰ :: [%shard_key] #min max shard_id 0 63 0 64 127 1 128 191 2 192 255 3 **shard_connection.txt** shard 구성 ë°ì´í„°ë² ì´ìФ ì„¤ì • 파ì¼ì¸ **shard_connection.txt** 파ì¼ì„ 아래와 ê°™ì´ ì„¤ì •í•œë‹¤. * shard #0ì˜ ì‹¤ì œ ë°ì´í„°ë² ì´ìФ ì´ë¦„ê³¼ connection ì •ë³´ * shard #1ì˜ ì‹¤ì œ ë°ì´í„°ë² ì´ìФ ì´ë¦„ê³¼ connection ì •ë³´ * shard #2ì˜ ì‹¤ì œ ë°ì´í„°ë² ì´ìФ ì´ë¦„ê³¼ connection ì •ë³´ * shard #3ì˜ ì‹¤ì œ ë°ì´í„°ë² ì´ìФ ì´ë¦„ê³¼ connection ì •ë³´ :: # shard-id real-db-name connection-info # * cubrid : hostname, hostname, ... 0 shard1 HostA 1 shard1 HostB 2 shard1 HostC 3 shard1 HostD 서비스 시작 ë° ëª¨ë‹ˆí„°ë§ ----------------------- **CUBRID SHARD 시작** CUBRID SHARD ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë ¤ë©´ 아래와 ê°™ì´ ë¸Œë¡œì»¤ë¥¼ 구ë™í•œë‹¤. :: sh> cubrid broker start @ cubrid broker start ++ cubrid broker start: success **CUBRID SHARD ìƒíƒœ 조회** 아래와 ê°™ì´ CUBRID SHARDì˜ ìƒíƒœë¥¼ 조회하여, ì„¤ì •ëœ íŒŒë¼ë¯¸í„°ì™€ í”„ë¡œì„¸ìŠ¤ì˜ ìƒíƒœë¥¼ 확ì¸í•œë‹¤. :: sh> cubrid broker status @ cubrid broker status % shard1 ---------------------------------------------------------------- ID PID QPS LQS PSIZE STATUS ---------------------------------------------------------------- 1-0-1 21272 0 0 53292 IDLE 1-1-1 21273 0 0 53292 IDLE 1-2-1 21274 0 0 53292 IDLE 1-3-1 21275 0 0 53292 IDLE sh> cubrid broker status -f @ cubrid broker status % shard1 ---------------------------------------------------------------------------------------------------------------------------------------------------------- ID PID QPS LQS PSIZE STATUS LAST ACCESS TIME DB HOST LAST CONNECT TIME SQL_LOG_MODE ---------------------------------------------------------------------------------------------------------------------------------------------------------- 1-0-1 21272 0 0 53292 IDLE 2013/01/31 15:00:24 shard1@HostA HostA 2013/01/31 15:00:25 - 1-1-1 21273 0 0 53292 IDLE 2013/01/31 15:00:24 shard1@HostB HostB 2013/01/31 15:00:25 - 1-2-1 21274 0 0 53292 IDLE 2013/01/31 15:00:24 shard1@HostC HostC 2013/01/31 15:00:25 - 1-3-1 21275 0 0 53292 IDLE 2013/01/31 15:00:24 shard1@HostD HostD 2013/01/31 15:00:25 - ì‘ìš© ì˜ˆì œ 프로그램 작성 ----------------------- 간단한 Java í”„ë¡œê·¸ëž¨ì„ ì´ìš©í•˜ì—¬ CUBRID SHARD ê¸°ëŠ¥ì´ ì •ìƒ ë™ìž‘í•¨ì„ í™•ì¸í•œë‹¤. **ì˜ˆì œ í…Œì´ë¸” ìƒì„±** ëª¨ë“ shard DBì—서 ì˜ˆì œ í”„ë¡œê·¸ëž¨ì„ ìœ„í•œ 임시 í…Œì´ë¸”ì„ ì•„ëž˜ì™€ ê°™ì´ ìƒì„±í•œë‹¤. :: sh> csql -C -u shard -p 'shard123' shard1@localhost -c "create table student (s_no int, s_name varchar, s_age int, primary key(s_no))" **ì˜ˆì œ 프로그램 작성** 다ìŒì€ 0~1023ë²ˆì˜ í•™ìƒ ì •ë³´ë¥¼ shard DB로 ìž…ë ¥í•˜ëŠ” ì˜ˆì œ 프로그램ì´ë‹¤. ì•žì„ ì ˆì°¨ì—서 ìˆ˜ì •í•œ **cubrid_broker.conf** 를 확ì¸í•˜ì—¬ 주소/í¬íЏ ë° ì‚¬ìš©ìž ì •ë³´ë¥¼ ì—°ê²° URLì— ì„¤ì •í•œë‹¤. .. code-block:: java import java.sql.DriverManager; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.PreparedStatement; import java.sql.Date; import java.sql.*; import cubrid.jdbc.driver.*; public class TestInsert { static { try { Class.forName("cubrid.jdbc.driver.CUBRIDDriver"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static void DoTest(int thread_id) throws SQLException { Connection connection = null; try { connection = DriverManager.getConnection("jdbc:cubrid:localhost:36000:shard1:::?charSet=utf8", "shard", "shard123"); connection.setAutoCommit(false); for (int i=0; i < 1024; i++) { String query = "INSERT INTO student VALUES (/*+ shard_key */ ?, ?, ?)"; PreparedStatement query_stmt = connection.prepareStatement(query); String name="name_" + i; query_stmt.setInt(1, i); query_stmt.setString(2, name); query_stmt.setInt(3, (i%64)+10); query_stmt.executeUpdate(); System.out.print("."); query_stmt.close(); connection.commit(); } connection.close(); } catch(SQLException e) { System.out.print("exception occurs : " + e.getErrorCode() + " - " + e.getMessage()); System.out.println(); connection.close(); } } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { DoTest(1); } catch(Exception e){ e.printStackTrace(); } } } **ì˜ˆì œ 프로그램 수행** 위ì—서 작성한 ì˜ˆì œ í”„ë¡œê·¸ëž¨ì„ ë‹¤ìŒê³¼ ê°™ì´ ìˆ˜í–‰í•œë‹¤. :: sh> javac -cp ".:$CUBRID/jdbc/cubrid_jdbc.jar" *.java sh> java -cp ".:$CUBRID/jdbc/cubrid_jdbc.jar" TestInsert **ê²°ê³¼ 확ì¸** ê° shard DBì—서 질ì˜ë¥¼ 수행하여 ì˜ë„한 대로 ë¶„í• ëœ ì •ë³´ê°€ ì •í™•í•˜ê²Œ ìž…ë ¥ë˜ì—ˆëŠ”ì§€ 확ì¸í•œë‹¤. * shard #0 :: sh> csql -C -u shard -p 'shard123' shard1@localhost -c "select * from student order by s_no" s_no s_name s_age ================================================ 0 'name_0' 10 1 'name_1' 11 2 'name_2' 12 3 'name_3' 13 ... * shard #1 :: sh> $ csql -C -u shard -p 'shard123' shard1@localhost -c "select * from student order by s_no" s_no s_name s_age ================================================ 64 'name_64' 10 65 'name_65' 11 66 'name_66' 12 67 'name_67' 13 ... * shard #2 :: sh> $ csql -C -u shard -p 'shard123' shard1@localhost -c "select * from student order by s_no" s_no s_name s_age ================================================= 128 'name_128' 10 129 'name_129' 11 130 'name_130' 12 131 'name_131' 13 ... * shard #3 :: sh> $ csql -C -u shard -p 'shard123' shard1@localhost -c "select * from student order by s_no" s_no s_name s_age ================================================ 192 'name_192' 10 193 'name_193' 11 194 'name_194' 12 195 'name_195' 13 ... .. _shard-configuration: 구성 ë° ì„¤ì • ============ 구성 ---- CUBRID SHARD는 미들웨어로서 ì•„ëž˜ì˜ ê·¸ë¦¼ê³¼ ê°™ì´ broker, proxy, CAS 프로세스로 구성ëœë‹¤. .. image:: /images/image50.png .. _default-shard-conf: ì„¤ì • ---- CUBRID SHARD ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë ¤ë©´ **cubrid_broker.conf** 파ì¼ì—서 SHARD ê´€ë ¨ í”„ë¡œì„¸ìŠ¤ë“¤ì˜ ì‹¤í–‰ì— í•„ìš”í•œ 파ë¼ë¯¸í„°ë¥¼ ì„¤ì •í•˜ê³ , shard ì—°ê²° 파ì¼(SHARD_CONNECTION_FILE)ê³¼ shard key 파ì¼(SHARD_KEY_FILE)ì„ ì„¤ì •í•´ì•¼ 한다. cubrid_broker.conf ^^^^^^^^^^^^^^^^^^ **cubrid_broker.conf** 는 CUBRID SHARD ê¸°ëŠ¥ì„ ì„¤ì •í• ë•Œ 사용한다. ì„¤ì • 시 **cubrid_broker.conf.shard**\ 를 ì°¸ê³ í•˜ë©°, **cubrid_broker.conf**\ ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì€ :ref:`broker-configuration`\ ì„ ì°¸ê³ í•œë‹¤. .. _shard-connection-file: shard ì—°ê²° 파ì¼(SHARD_CONNECTION_FILE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CUBRID SHARD는 브로커 êµ¬ë™ ì‹œ **cubrid_broker.conf**\ ì˜ **SHARD_CONNECTION_FILE** 파ë¼ë¯¸í„°ì— ì§€ì •ëœ shard ì—°ê²° ì„¤ì • 파ì¼ì„ 로딩하여 backend shard DBì™€ì˜ ì—°ê²°ì„ ìˆ˜í–‰í•œë‹¤. ì„¤ì • í• ìˆ˜ 있는 shard DB ì˜ ìµœëŒ€ 개수는 256 ê°œ ì´ë‹¤. **cubrid_broker.conf**\ ì— **SHARD_CONNECTION_FILE**\ ì„ ë³„ë„로 ì§€ì •í•˜ì§€ ì•Šì€ ê²½ìš°ì—는 ê¸°ë³¸ê°’ì¸ **shard_connection.txt** 파ì¼ì„ 로딩한다. **기본 형ì‹** shard ì—°ê²° ì„¤ì • 파ì¼ì˜ 기본ì ì¸ ì˜ˆì™€ 형ì‹ì€ 아래와 같다. :: # # shard-id real-db-name connection-info # * cubrid : hostname, hostname, ... # CUBRID 0 shard1 HostA 1 shard1 HostB 2 shard1 HostC 3 shard1 HostD .. note:: ì¼ë°˜ì ì¸ CUBRID ì„¤ì •ê³¼ 마찬가지로 # ì´í›„ ë‚´ìš©ì€ ì£¼ì„으로 처리ëœë‹¤. **CUBRID** backend shard DBê°€ CUBRIDì¸ ê²½ìš° ì—°ê²° ì„¤ì • 파ì¼ì˜ 형ì‹ì€ 다ìŒê³¼ 같다. :: # CUBRID # shard-id real-db-name connection-info # shard ì‹ë³„ìž( >0 ) ê° backend shard DB ì˜ ì‹¤ì œ ì´ë¦„ 호스트 ì´ë¦„ 0 shard_db_1 host1 1 shard_db_2 host2 2 shard_db_3 host3 3 shard_db_4 host4 CUBRIDì˜ ê²½ìš° 별ë„ì˜ backend shard DBì˜ í¬íЏ 번호를 위 ì„¤ì • 파ì¼ì— ì§€ì •í•˜ì§€ ì•Šê³ , **cubrid.conf**\ ì˜ **CUBRID_PORT_ID** 파ë¼ë¯¸í„°ë¥¼ 사용한다. **cubrid.conf** 파ì¼ì€ 기본ì 으로 **$CUBRID/conf** ë””ë ‰í„°ë¦¬ì— ìœ„ì¹˜í•œë‹¤. :: $ vi cubrid.conf ... # TCP port id for the CUBRID programs (used by all clients). cubrid_port_id=41523 .. _shard-key-configuration-file: shard key 파ì¼(SHARD_KEY_FILE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CUBRID SHARD는 시작 시 기본 ì„¤ì • 파ì¼ì¸ **cubrid_broker.conf** ì˜ **SHARD_KEY_FILE** 파ë¼ë¯¸í„°ì— ì§€ì •ëœ shard key ì„¤ì • 파ì¼ì„ 로딩하여 ì‚¬ìš©ìž ìš”ì²ì„ ì–´ë–¤ backend shard DBì—서 처리해야 í• ì§€ ê²°ì •í•˜ëŠ” ë° ì‚¬ìš©í•œë‹¤. **cubrid_broker.conf** ì— **SHARD_KEY_FILE** ì„ ë³„ë„로 ì§€ì •í•˜ì§€ ì•Šì€ ê²½ìš°ì—는 ê¸°ë³¸ê°’ì¸ **shard_key.txt** 파ì¼ì„ 로딩한다. **형ì‹** shard key ì„¤ì • 파ì¼ì˜ 예와 형ì‹ì€ 다ìŒê³¼ 같다. :: [%student_no] #min max shard_id 0 31 0 32 63 1 64 95 2 96 127 3 128 159 0 160 191 1 192 223 2 224 255 3 * [%shard_key_name] : shard keyì˜ ì´ë¦„ì„ ì§€ì • * min : shard key 해시 ê²°ê³¼ì˜ ìµœì†Œê°’ 범위 * max : shard key 해시 ê²°ê³¼ì˜ ìµœëŒ€ 범위 * shard_id : shard ì‹ë³„ìž .. note:: ì¼ë°˜ì ì¸ CUBRID ì„¤ì •ê³¼ 마찬가지로 # ì´í›„ ë‚´ìš©ì€ ì£¼ì„으로 처리ëœë‹¤. .. warning:: * shard keyì˜ minì€ í•ìƒ 0부터 시작해야 한다. * max는 최대 255까지 ì„¤ì •í•´ì•¼ 한다. * min~max 사ì´ì—는 빈 ê°’ì´ ì¡´ìž¬í•˜ë©´ 안 ëœë‹¤. * 내장 해시 함수를 사용하는 경우 **SHARD_KEY_MODULAR** 파ë¼ë¯¸í„° ê°’(최소 1, 최대 256)ì„ ì´ˆê³¼í• ìˆ˜ 없다. * shard key 해시 결과는 0 ~ (**SHARD_KEY_MODULAR** - 1)ì˜ ë²”ìœ„ì— ë°˜ë“œì‹œ í¬í•¨ë˜ì–´ì•¼ 한다. .. _setting-user-defined-hash-function: ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수 ^^^^^^^^^^^^^^^^^^^^^ CUBRID SHARD는 질ì˜ë¥¼ ìˆ˜í–‰í• shard를 ì„ íƒí•˜ê¸° 위해 shard key를 해싱한 결과와 메타ë°ì´í„° ì„¤ì • ì •ë³´ë¥¼ ì´ìš©í•œë‹¤. ì´ë¥¼ 위해 기본 ë‚´ìž¥ëœ í•´ì‹œ 함수를 사용하거나, ë˜ëŠ” 사용ìžê°€ 별ë„로 해시 함수를 ì •ì˜í• 수 있다. **ë‚´ìž¥ëœ ê¸°ë³¸ 해시 함수** **cubrid_broker.conf** ì˜ **SHARD_KEY_LIBRARY_NAME**, **SHARD_KEY_FUNCTION_NAME** 파ë¼ë¯¸í„°ë¥¼ ì„¤ì •í•˜ì§€ 않는 경우 기본 ë‚´ìž¥ëœ í•´ì‹œ 함수를 ì´ìš©í•˜ì—¬ shard key를 해시하며, 기본 해시 í•¨ìˆ˜ì˜ ë‚´ìš©ì€ ì•„ëž˜ì™€ 같다. * shard_keyê°€ ì •ìˆ˜ì¸ ê²½ìš° :: 기본 해시 함수(shard_key) = shard_key mod SHARD_KEY_MODULAR 파ë¼ë¯¸í„°(기본값 256) * shard_keyê°€ 문ìžì—´ì¸ 경우 :: 기본 해시 함수(shard_key) = shard_key[0] mod SHARD_KEY_MODULAR 파ë¼ë¯¸í„°(기본값 256) **ì‚¬ìš©ìž í•´ì‹œ 함수 ì„¤ì •** CUBRID SHARD는 기본 ë‚´ìž¥ëœ í•´ì‹œ 함수 ì™¸ì— ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수를 ì´ìš©í•˜ì—¬ 질ì˜ì— í¬í•¨ëœ shard key를 í•´ì‹±í• ìˆ˜ 있다. **ë¼ì´ë¸ŒëŸ¬ë¦¬ 구현 ë° ìƒì„±** ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수는 실행 ì‹œê°„ì— ë¡œë”© 가능한 **.so** í˜•íƒœì˜ ë¼ì´ë¸ŒëŸ¬ë¦¬ë¡œ 구현ë˜ì–´ì•¼ 하며 í”„ë¡œí† íƒ€ìž…ì€ ì•„ëž˜ì™€ 같다. .. code-block:: c /* return value : success - shard key id(>0) fail - invalid argument(ERROR_ON_ARGUMENT), shard key id make fail(ERROR_ON_MAKE_SHARD_KEY) type : shard key value type val : shard key value */ typedef int (*FN_GET_SHARD_KEY) (const char *shard_key, T_SHARD_U_TYPE type, const void *val, int val_size); * 해시 í•¨ìˆ˜ì˜ ë°˜í™˜ ê°’ì€ **shard_key.txt** ì„¤ì • 파ì¼ì˜ 해시 ê²°ê³¼ ë²”ìœ„ì— ë°˜ë“œì‹œ í¬í•¨ë˜ì–´ì•¼ 한다. * ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ 빌드하기 위해서는 반드시 **$CUBRID/include/shard_key.h** 파ì¼ì„ include해야 한다. ì´ íŒŒì¼ì—서 반환 가능한 ì—러 코드 등 ìžì„¸í•œ ë‚´ìš©ë„ í™•ì¸í• 수 있다. **cubrid_broker.conf ì„¤ì • íŒŒì¼ ë³€ê²½** ìƒì„±í•œ ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수를 ë°˜ì˜í•˜ê¸° 위해서는 **cubrid_broker.conf**\ ì˜ **SHARD_KEY_LIBRARY_NAME**, **SHARD_KEY_FUNCTION_NAME** 파ë¼ë¯¸í„°ë¥¼ 구현 ë‚´ìš©ì— ë§žë„ë¡ ì„¤ì •í•´ì•¼ 한다. * **SHARD_KEY_LIBRARY_NAME** : ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ ë¼ì´ë¸ŒëŸ¬ë¦¬ì˜ (ì ˆëŒ€) 경로 * **SHARD_KEY_FUNCTION_NAME** : ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ í•¨ìˆ˜ì˜ ì´ë¦„ **ì˜ˆì œ** 다ìŒì€ ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수를 사용한 예ì´ë‹¤. ë¨¼ì € **shard_key.txt** ì„¤ì • 파ì¼ì„ 확ì¸í•œë‹¤. :: [%student_no] #min max shard_id 0 31 0 32 63 1 64 95 2 96 127 3 128 159 0 160 191 1 192 223 2 224 255 3 ì‚¬ìš©ìž ì§€ì • 해시 함수를 ì„¤ì •í•˜ê¸° 위해서는 실행 ì‹œê°„ì— ë¡œë”© 가능한 **.so** í˜•íƒœì˜ ê³µìœ ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ ë¨¼ì € 구현해야 한다. 해시 í•¨ìˆ˜ì˜ ê²°ê³¼ëŠ” ì•žì„ ê³¼ì •ì—서 확ì¸í•œ **shard_key.txt** ì„¤ì • 파ì¼ì— ì •ì˜ëœ 해시 ê²°ê³¼ì˜ ë²”ìœ„ ì•ˆì— í¬í•¨ë˜ëŠ” ê°’ì´ì–´ì•¼ 한다. 다ìŒì€ 간단한 구현 예ì´ë‹¤. * shard_keyê°€ ì •ìˆ˜ì¸ ê²½ìš° * shard_keyê°€ í™€ìˆ˜ì¸ ê²½ìš° shard #0ì„ ì„ íƒ * shard_keyê°€ ì§ìˆ˜ì¸ 경우 shard #1ì„ ì„ íƒ * shard_keyê°€ 문ìžì—´ì¸ 경우 * shard_key 문ìžì—´ì´ 'a', 'A'로 시작ë˜ëŠ” 경우 shard #0ì„ ì„ íƒ * shard_key 문ìžì—´ì´ 'b', 'B'로 시작ë˜ëŠ” 경우 shard #1ì„ ì„ íƒ * shard_key 문ìžì—´ì´ 'c', 'C'로 시작ë˜ëŠ” 경우 shard #2를 ì„ íƒ * shard_key 문ìžì—´ì´ 'd', 'D'로 시작ë˜ëŠ” 경우 shard #3ì„ ì„ íƒ .. code-block:: c // <shard_key_udf.c> #include <string.h> #include <stdio.h> #include <unistd.h> #include "shard_key.h" int fn_shard_key_udf (const char *shard_key, T_SHARD_U_TYPE type, const void *value, int value_len) { unsigned int ival; unsigned char c; if (value == NULL) { return ERROR_ON_ARGUMENT; } switch (type) { case SHARD_U_TYPE_INT: ival = (unsigned int) (*(unsigned int *) value); if (ival % 2) { return 32; // shard #1 } else { return 0; // shard #0 } break; case SHARD_U_TYPE_STRING: c = (unsigned char) (((unsigned char *) value)[0]); switch (c) { case 'a': case 'A': return 0; // shard #0 case 'b': case 'B': return 32; // shard #1 case 'c': case 'C': return 64; // shard #2 case 'd': case 'D': return 96; // shard #3 default: return ERROR_ON_ARGUMENT; } break; default: return ERROR_ON_ARGUMENT; } return ERROR_ON_MAKE_SHARD_KEY; } ì‚¬ìš©ìž ì§€ì • 해시 함수를 ê³µìœ ë¼ì´ë¸ŒëŸ¬ë¦¬ 형태로 빌드한다. 다ìŒì€ 해시 함수 빌드를 위한 Makefileì˜ ì˜ˆì´ë‹¤. :: # Makefile CC = gcc LIBS = $(LIB_FLAG) CFLAGS = $(CFLAGS_COMMON) -fPIC -I$(CUBRID)/include -I$(CUBRID_SRC)/src/broker SHARD_CC = gcc -g -shared -Wl,-soname,shard_key_udf.so SHARD_KEY_UDF_OBJS = shard_key_udf.o all:$(SHARD_KEY_UDF_OBJS) $(SHARD_CC) $(CFLAGS) -o shard_key_udf.so $(SHARD_KEY_UDF_OBJS) $(LIBS) clean: -rm -f *.o core shard_key_udf.so ì‚¬ìš©ìž ì •ì˜ í•´ì‹œ 함수를 í¬í•¨í•˜ê¸° 위해 **SHARD_KEY_LIBRARY_NAME**, **SHARD_KEY_FUNCTION_NAME** 파ë¼ë¯¸í„°ë¥¼ 위 구현과 ì¼ì¹˜í•˜ë„ë¡ ìˆ˜ì •í•œë‹¤. :: [%student_no] SHARD_KEY_LIBRARY_NAME =$CUBRID/conf/shard_key_udf.so SHARD_KEY_FUNCTION_NAME =fn_shard_key_udf .. note:: * ì‘ìš© 프로그램ì—서 ì‚¬ìš©ìž í•´ì‹œ 함수를 ì •ì˜í• 때 shard keyì˜ ìž…ë ¥ 값으로 16bit(short), 32bit(int), 64bit(INT64) integer를 ì‚¬ìš©í• ìˆ˜ 있다. * VARCHAR를 사용해야 ë˜ëŠ” 경우 사용ìžê°€ 해시 함수를 ì •ì˜í•´ì•¼ 한다. .. _shard-start-monitoring: êµ¬ë™ ë° ëª¨ë‹ˆí„°ë§ ================ cubrid broker ìœ í‹¸ë¦¬í‹°ë¥¼ ì´ìš©í•˜ì—¬ CUBRID SHARD ê¸°ëŠ¥ì„ êµ¬ë™í•˜ê±°ë‚˜ ì •ì§€í• ìˆ˜ ìžˆê³ , ê°ì¢… ìƒíƒœ ì •ë³´ë¥¼ ì¡°íšŒí• ìˆ˜ 있다. 보다 ìžì„¸í•œ ë‚´ìš©ì€ :ref:`broker`\ 를 ì°¸ê³ í•œë‹¤. ì„¤ì • 테스트 =========== cubrid broker test ëª…ë ¹ì„ ì´ìš©í•˜ì—¬ ì„¤ì •ì´ ì •ìƒ ë™ìž‘하는지 í…ŒìŠ¤íŠ¸í• ìˆ˜ 있다. 보다 ìžì„¸í•œ ë‚´ìš©ì€ :ref:`broker-test`\ 를 ì°¸ê³ í•œë‹¤. .. _shard-logs: CUBRID SHARD 로그 ================= SHARD 구ë™ê³¼ ê´€ë ¨ëœ ë¡œê·¸ì—는 ì ‘ì† ë¡œê·¸, 프ë¡ì‹œ 로그, SQL 로그, ì—러 로그가 있다. ê°ê° ë¡œê·¸ì˜ ì €ìž¥ ë””ë ‰í„°ë¦¬ ë³€ê²½ì€ SHARD 환경 ì„¤ì • 파ì¼(**cubrid_broker.conf**) ì˜ **LOG_DIR**, **ERROR_LOG_DIR**, **PROXY_LOG_DIR** 파ë¼ë¯¸í„°ë¥¼ 통해 ì„¤ì •í• ìˆ˜ 있다. SHARD PROXY 로그 ---------------- **ì ‘ì† ë¡œê·¸** * 파ë¼ë¯¸í„°: **ACCESS_LOG** * 설명: í´ë¼ì´ì–¸íŠ¸ì˜ ì ‘ì†ì„ logging한다(기존 브로커는 CASì—서 로그를 남긴다). * 기본 ì €ìž¥ ë””ë ‰í„°ë¦¬: $CUBRID/log/broker/ * íŒŒì¼ ì´ë¦„: <broker_name>_<proxy_index>.access * 로그 형ì‹: CASì—서 남기는 access log와 cas_index ì´ì™¸ì˜ ëª¨ë“ string ë™ì¼ :: 10.24.18.67 - - 1340243427.828 1340243427.828 2012/06/21 10:50:27 ~ 2012/06/21 10:50:27 23377 - -1 shard1 shard1 10.24.18.67 - - 1340243427.858 1340243427.858 2012/06/21 10:50:27 ~ 2012/06/21 10:50:27 23377 - -1 shard1 shard1 10.24.18.67 - - 1340243446.791 1340243446.791 2012/06/21 10:50:46 ~ 2012/06/21 10:50:46 23377 - -1 shard1 shard1 10.24.18.67 - - 1340243446.821 1340243446.821 2012/06/21 10:50:46 ~ 2012/06/21 10:50:46 23377 - -1 shard1 shard1 **프ë¡ì‹œ 로그** * 파ë¼ë¯¸í„°: **SHARD_PROXY_LOG_DIR** * 설명: proxy ë‚´ë¶€ì˜ ë™ìž‘ì„ logging한다. * 기본 ì €ìž¥ ë””ë ‰í„°ë¦¬: $CUBRID/log/broker/proxy_log * íŒŒì¼ ì´ë¦„: <broker_name>_<proxy_index>.log :: 06/21 10:50:46.822 [SRD] ../../src/broker/shard_proxy_io.c(1045): New socket io created. (fd:50). 06/21 10:50:46.822 [SRD] ../../src/broker/shard_proxy_io.c(2517): New client connected. client(client_id:3, is_busy:Y, fd:50, ctx_cid:3, ctx_uid:4). 06/21 10:50:46.825 [DBG] ../../src/broker/shard_proxy_io.c(3298): Shard status. (num_cas_in_tran=1, shard_id=2). 06/21 10:50:46.827 [DBG] ../../src/broker/shard_proxy_io.c(3385): Shard status. (num_cas_in_tran=0, shard_id=2). **프ë¡ì‹œ 로그 ë ˆë²¨** * 파ë¼ë¯¸í„°: **SHARD_PROXY_LOG** * 프ë¡ì‹œ 로그 ë ˆë²¨ ì •ì±…: ìƒìœ„ levelì„ ì„¤ì •í•˜ë©´ í•˜ìœ„ì˜ ëª¨ë“ ë¡œê·¸ê°€ 남는다. * 예) SCHEDULEì„ ì„¤ì •í•˜ë©´, ERROR | TIMEOUT | NOTICE | SHARD | SCHEDULE 로그를 ëª¨ë‘ ë‚¨ê¸´ë‹¤. * 프ë¡ì‹œ 로그 ë ˆë²¨ í•목 * NONE or OFF: 로그를 남기지 않는다. * ERROR(default): ë‚´ë¶€ì 으로 ì—러가 ë°œìƒí•˜ì—¬ ì •ìƒì 으로 처리ë˜ì§€ 못하는 경우 * TIMEOUT: session timeoutì´ë‚˜ query timeout ë“±ì˜ timeout * NOTICE: 힌트 없는 query ë° ê¸°íƒ€ ì—러는 아닌 경우 * SHARD: client ì˜ requestê°€ ì–´ë–¤ shardì˜ ì–´ë–¤ CAS로 갔는지, ê·¸ê²ƒì´ ë‹¤ì‹œ client response ë˜ì—ˆëŠ”ì§€ ë“±ì˜ scheduling * SCHEDULE: 힌트 parsing ë° hash를 통해 shard key id ê°€ì ¸ì˜¤ëŠ” 것 ë“±ì˜ shard processing * ALL: ëª¨ë“ ë¡œê·¸ SHARD CAS 로그 -------------- **SQL 로그** * 파ë¼ë¯¸í„° : **SQL_LOG** * 설명 : prepare/execute/fetch ë“±ì˜ query ë° ê¸°íƒ€ CAS ì •ë³´ë¥¼ logging한다. * 기본 ì €ìž¥ ë””ë ‰í„°ë¦¬ : $CUBRID/log/broker/sql_log * íŒŒì¼ ì´ë¦„ : <broker_name>_<proxy_index>_<shard_index>_<cas_index>.sql.log :: 13-06-21 10:13:00.005 (0) STATE idle 13-06-21 10:13:01.035 (0) CAS TERMINATED pid 31595 13-06-21 10:14:20.198 (0) CAS STARTED pid 23378 13-06-21 10:14:21.227 (0) connect db shard1@HostA user dba url shard1 session id 3 13-06-21 10:14:21.227 (0) DEFAULT isolation_level 3, lock_timeout -1 13-06-21 10:50:28.259 (1) prepare srv_h_id 1 13-06-21 10:50:28.259 (0) auto_rollback 13-06-21 10:50:28.259 (0) auto_rollback 0 **ì—러 로그** * 파ë¼ë¯¸í„° : **ERROR_LOG_DIR** * 설명 : CUBRIDì˜ ê²½ìš° cs libraryì—서 EID ë° error stringì„ í•´ë‹¹ 파ì¼ì— logging한다. * 기본 ì €ìž¥ ë””ë ‰í„°ë¦¬ : $CUBRID/log/broker/error_log * íŒŒì¼ ì´ë¦„ : <broker_name>_<proxy_index>_<shard_index>_<cas_index>.err :: Time: 06/21/13 10:50:27.776 - DEBUG *** file ../../src/transaction/boot_cl.c, line 1409 trying to connect 'shard1@localhost' Time: 06/21/13 10:50:27.776 - DEBUG *** file ../../src/transaction/boot_cl.c, line 1418 ping server with handshake Time: 06/21/13 10:50:27.777 - DEBUG *** file ../../src/transaction/boot_cl.c, line 966 boot_restart_client: register client { type 4 db shard1 user dba password (null) program cubrid_cub_cas_1 login cubrid_user host HostA pid 23270 } ì œì•½ ì‚¬í• ========= **Linuxë§Œ ì§€ì›** Linuxì—서만 CUBRID SHARD ê¸°ëŠ¥ì„ ì‚¬ìš©í• ìˆ˜ 있다. **í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ì€ í•˜ë‚˜ì˜ shard DBì—서만 수행 가능** í•˜ë‚˜ì˜ íŠ¸ëžœìžì…˜ì€ ì˜¤ì§ í•˜ë‚˜ì˜ shard DBì—서만 수행ë˜ì–´ì•¼ 하며, ë”°ë¼ì„œ 아래와 ê°™ì€ ì œì•½ì‚¬í•ì´ ì¡´ìž¬í•œë‹¤. * shard key 변경(**UPDATE**)으로 ì¸í•´ 여러 shard DBì˜ ë°ì´í„°ë¥¼ 변경하는 ê²ƒì€ ë¶ˆê°€ëŠ¥í•˜ë©°, 필요하다면 **DELETE** / **INSERT** 를 ì´ìš©í•œë‹¤. * 2ê°œ ì´ìƒì˜ ìƒ¤ë“œì— ëŒ€í•œ 질ì˜(join, sub-query, or, union, group by, between, like, in, exist, any/some/all 등)를 ì§€ì›í•˜ì§€ 않는다. **세션 ì •ë³´ëŠ” ê° shard DB ë‚´ì—서만 ìœ íš¨** 세션 ì •ë³´ê°€ ê° shard DB ë‚´ì—서만 ìœ íš¨í•˜ë¯€ë¡œ, :func:`LAST_INSERT_ID`\ 와 ê°™ì€ ì„¸ì…˜ ê´€ë ¨ í•¨ìˆ˜ì˜ ê²°ê³¼ê°€ ì˜ë„한 바와 다를 수 있다. **SET NAMES 문 ì§€ì› ì•ˆ 함** SHARD 구성 환경ì—서는 SET NAMES ë¬¸ì´ ì •ìƒ ë™ìž‘하지 ì•Šì„ ìˆ˜ 있으므로, ì‚¬ìš©ì„ ê¶Œìž¥í•˜ì§€ 않는다. **auto increment는 ê° shard DB ë‚´ì—서만 ìœ íš¨** auto increment ì†ì„± ë˜ëŠ” SERIAL ë“±ì˜ ê°’ì´ ê° shard DB ë‚´ì—서만 ìœ íš¨í•˜ë¯€ë¡œ, ì˜ë„한 것과 다른 ê°’ì„ ë°˜í™˜í• ìˆ˜ 있다. **SHARD 힌트 êµ¬ë¬¸ì´ ìž‘ì„±ëœ DDL êµ¬ë¬¸ì€ ì§€ì› ì•ˆí•¨** SHARD 구성 환경ì—서 스키마 ìƒì„± ë° ë³€ê²½ ë“±ì˜ DDLêµ¬ë¬¸ì€ SHARD 힌트가 ì§€ì› ë˜ì§€ 않으므로 ê°ê°ì˜ SHARD DBì— ì ‘ì†í•˜ì—¬ 스키마 ìƒì„± ë° ë³€ê²½ì„ ì²˜ë¦¬í•˜ì—¬ì•¼ 한다. shard_id(0)ì€ ì •ìƒì 으로 처리ë˜ë©°, shard_id(1)부터는 ì—러를 ë°œìƒì‹œí‚¨ë‹¤. 오류 예시) :: CREATE TABLE foo (col1 INT NOT NULL) /*+ SHARD_ID(1) / :: DROP TABLE IF EXISTS foo /+ SHARD_ID(1) */