Contents

9.3 릴리스 노트

릴리스 노트 정보

본 문서는 CUBRID 9.3(빌드번호 9.3.0.0206)에 관한 정보를 포함한다. CUBRID 9.3은 CUBRID 9.2에서 발견된 오류 수정 및 기능 개선과 이전 버전들에 반영된 모든 오류 수정 및 기능 개선을 포함한다.

9.0 Beta, 9.1, 9.2에 대한 정보는 9.0 릴리스 노트, 9.1 릴리스 노트, 9.2 릴리스 노트에서 확인할 수 있다.

CUBRID 2008 R4.4 버전에 대한 정보는 http://www.cubrid.org/manual/844/ko/release_note/r844.html에서 확인할 수 있다.

CUBRID 2008 R4.3 이하 버전에 대한 정보는 http://release.cubrid.org/ko에서 확인할 수 있다.

릴리스 특징

CUBRID 9.3은 CUBRID 9.2를 안정화하고 개선한 버전이다.

CUBRID 9.3은 CUBRID 9.2와 데이터베이스 볼륨이 호환된다. CUBRID 9.1 및 이전 버전 사용자는 반드시 데이터베이스를 마이그레이션해야 한다. 이와 관련하여 업그레이드 절을 참고한다.

SQL 함수 및 구문 추가

  • SELECT FOR UPDATE 구문을 지원한다.
  • 스키마 잠금을 지원한다.
  • 데이터베이스 내부 정보를 확인할 수 있는 각종 SHOW 문을 제공한다.
  • SHA-1, SHA-2, TO_BASE64, FROM_BASE64 함수를 지원한다.

성능 향상

  • 통계 정보 갱신 시 샘플링 방식을 적용하여 통계 정보 갱신 시간이 단축되었다.
  • INSERT 연산의 수행 성능이 향상되었다.
  • 버퍼 매니저의 페이지 교체 정책 개선으로 SELECT 및 SCAN 작업 시 성능이 향상되었다.
  • Loose index scan을 지원한다.
  • 집계 및 분석 함수를 포함하는 질의의 성능이 향상되었다.
  • LIKE 질의 성능이 향상되었다.
  • 다량의 DELETE 이후 INSERT 수행이 장시간 걸리는 문제가 개선되었다.
  • TIMESTAMP 타입의 데이터 입력 시 성능이 향상되었다.
  • 한 번에 여러 개의 연결을 생성하는데 소요되는 시간을 줄였다.
  • 독립 모드(--SA-mode)로 인덱스 생성 시 소요되는 시간을 줄였다.
  • 동시에 같은 테이블에 많은 FULL SCAN 작업이 수행되는데 소요되는 시간을 줄였다.
  • Windows 환경에서 응용 프로그램을 통해 질의를 수행하는 경우 Linux보다 상대적으로 느려지는 현상이 개선되었다.

HA 기능 추가

  • 복제 반영 시간을 단축시키는 유틸리티가 추가되었다.
  • 브로커가 레플리카에만 접속하는 것이 가능하게 되었다.
  • CSQL에 특정 옵션을 제공하여 슬레이브 또는 레플리카에 쓰기가 가능하게 되었다.

운영 편의성 개선

  • SHARD proxy 내부의 상태 정보가 강화되었다.
  • DB에 지정한 질의가 정상 수행되는지 테스트해 보는 명령이 추가되었다.

다국어 지원 관련 안정화

  • 콜레이션이 서로 다른 문자열을 비교하거나 SQL 함수에서 콜레이션이 서로 다른 인자들을 입력할 때 발생하는 여러 오류가 수정되었다.
  • 호스트 변수의 콜레이션 추정과 관련된 오류들이 다수 수정되었다.

동작 변경

  • "cubrid heartbeat reload" 명령을 수행한 이후 "cubrid heartbeat replication start/stop <node_name>"도 같이 수행해야 한다.
  • CCI의 loginTimeout과 JDBC의 connectTimeout이 최초 접속뿐만 아니라 내부 재접속(EXECUTE 수행 중 재접속) 시에도 적용된다. 기본값이 무한대기에서 30초로 변경되었다.
  • cubrid.conf의 log_buffer_size의 최소값이 48KB에서 2MB로 변경되었다.
  • "cubrid broker status" 명령에 "-b" 또는 "-f" 옵션이 사용될 때 브로커 이름이 영문 20자를 넘으면 넘는 문자열의 출력을 생략했으나 수정 이후 모두 출력한다.
  • JDBC의 연결 객체에 사용자 계정 또는 암호를 ""로 입력할 때 연결 URL의 사용자 또는 암호를 따르도록 수정되었다.
  • 트랜잭션 수행 도중 서버 프로세스가 재시작되거나 HA 환경에서 절체(failover)가 발생한 경우, 커밋이나 롤백의 명시없이 이어서 실행하는 질의는 에러로 처리하게 되었다.
  • 정렬 병합 조인(sort merge join)에 대한 질의 실행 계획이 생성되지 않게 변경되었으므로, 정렬 병합 조인을 질의 실행 계획 후보에 포함하고 싶다면 해당 질의문에 USE_MERGE 힌트를 추가하거나 cubrid.conf의 optimizer_enable_merge_join 값을 yes로 설정해야 한다.

드라이버 호환성

  • 9.3 버전의 JDBC와 CCI 드라이버는 CUBRID 9.2, 9.1 및 CUBRID 2008 R4.1, R4.3, R4.4 버전의 DB와 연동된다.

이외에도 많은 안정성 이슈가 수정되었다. 보다 자세한 변경 사항은 아래의 내용을 참고하며, 이전 버전 사용자는 동작 변경 절과 신규 주의 사항 절을 반드시 확인하도록 한다.

기능 추가

SQL

SELECT FOR UPDATE 구문 지원 (CUBRIDSUS-10607)

SELECT * FROM t1 INNER JOIN t2 ON t1.i=t2.i ORDER BY 1 FOR UPDATE OF t1, t2;

스키마 잠금 추가 (CUBRIDSUS-11114)

스키마 작업과 관련하여 다음 두 가지 잠금이 추가되었다.

  • SCH-S: 스키마 안정 잠금(Schema stability lock). 이 잠금은 질의 컴파일을 수행하는 동안 획득되며 질의에 포함된 스키마가 다른 트랜잭션에 의해 수정되지 않음을 보장한다.
  • SCH-M: 스키마 수정 잠금(Schema modification lock). 이 잠금은 DDL(ALTER/CREATE/DROP) 작업 시 획득되며 다른 트랜잭션이 수정된 스키마에 접근하는 것을 방지한다.

스키마 잠금이 적용되면서, 풀 스캔(full scan) UPDATE/DELETE 문이 동시에 수행될 때 수정 이전 버전에서 발생하던 교착 상태 문제가 해결되었다.

SHOW ACCESS STATUS 구문 추가 (CUBRIDSUS-12643)

데이터베이스 계정에 대한 로그인 정보를 출력하는 구문을 추가했다. 이 구문은 "DBA" 계정만 사용 가능하다.

단, 로그인 정보는 데이터베이스가 재시작되면 초기화되며, HA 환경에서 복제되지 않으므로 각 노드마다 다른 결과를 보여준다.

SHOW ACCESS STATUS;
  user_name   last_access_time              last_access_host    program_name
=============================================================================
  'DBA'       08:19:31.000 PM 02/10/2014    127.0.0.1           'csql'
  'PUBLIC'    NULL                          NULL                NULL

SHOW VOLUME HEADER 문 추가 (CUBRIDSUS-12505)

특정 볼륨의 헤더 정보를 출력하는 "SHOW VOLUME HEADER" 문을 추가했다.

SHOW VOLUME HEADER OF 1;

SHOW LOG HEADER, SHOW ARCHIVE LOG HEADER 문 추가 (CUBRIDSUS-12504)

활성 로그(active log)의 헤더 정보를 출력하는 SHOW LOG HEADER 구문을 추가했다.

SHOW LOG HEADER
SHOW LOG HEADER OF '/home/cubriddb/demodb_lgat'

첫 번째 문장은 메모리의 헤더 정보를 출력하며, 두 번째 문장은 지정한 파일의 헤더 정보를 출력한다.

그리고, 보관 로그의 헤더 정보를 출력하는 SHOW ARCHIVE LOG HEADER 구문을 추가했다.

SHOW ARCHIVE LOG HEADER OF 'demodb_lgar001';

SHOW HEAP HEADER/CAPACITY 문 추가 (CUBRIDSUS-12506)

"SHOW HEAP HEADER OF table_name" 문은 지정한 테이블의 헤더 페이지를 출력한다. "SHOW HEAP CAPACITY OF table_name" 문은 테이블의 용량을 출력한다.

SHOW INDEX HEADER/CAPACITY 문 추가 (CUBRIDSUS-12507)

"SHOW INDEX HEADER" 문은 지정한 인덱스의 헤더 페이지를 출력한다. "SHOW INDEX CAPACITY" 문은 지정한 인덱스의 용량을 출력한다.

SHOW SLOTTED PAGE HEADER/SLOTS 문 추가 (CUBRIDSUS-12508)

"SHOW SLOTTED PAGE HEADER OF VOLUME=vol_num AND PAGE=page_num" 문은 명시된 슬롯 페이지의 헤더 정보를 출력한다. "SHOW SLOTTED PAGE SLOTS OF VOLUME=vol_num AND PAGE=page_num" 문은 명시된 슬롯 페이지의 모든 슬롯 정보를 출력한다.

SHA-1, SHA-2 함수 추가 (CUBRIDSUS-10546)

SHA-1 암호화 함수와 SHA-2 암호화 함수를 추가했다.

TO_BASE64, FROM_BASE64 함수 추가 (CUBRIDSUS-11119)

base-64 암호화와 복호화를 수행하는 TO_BASE64, FROM_BASE64 함수를 추가했다.

어떤 칼럼의 제약 조건이 NULL일 때 데이터 검사 없이 제약 조건을 NOT NULL로 변경하는 것을 허용하는 SKIP_UPDATE_NULL 힌트 추가 (CUBRIDSUS-13221)

NULL을 NOT NULL로 제약 조건을 변경하는 경우 기존 버전에서는 hard default로 값을 업데이트하는 과정으로 인해 많은 시간이 소요되며, 이 문제를 해소하기 위해 수정된 버전에서는 SKIP_UPDATE_NULL를 제공한다. 이 힌트 사용 이후 사용자는 NOT NULL 제약 조건과 불일치하는 NULL 값이 존재할 수 있음을 인지해야 한다.

ALTER /*+ SKIP_UPDATE_NULL */ TABLE foo MODIFY col INT NOT NULL;

HA

브로커가 레플리카에만 접속하도록 설정하는 파라미터 추가 (CUBRIDSUS-12232)

cubrid_broker.conf에 REPLICA_ONLY 파라미터를 추가하여, 이 값이 ON이면 해당 브로커가 레플리카에만 접속하도록 수정했다. ACCESS_MODE의 값이 RW이고 REPLICA_ONLY의 값이 ON이면 레플리카에 직접 접속하여 쓰기가 가능해진다. 단, 레플리카에 직접 쓰는 데이터는 복제되지 않는다.

슬레이브 DB 또는 레플리카 DB에 쓰기가 가능한 옵션을 CSQL에 추가 (CUBRIDSUS-12232)

CSQL에 --write-on-standby 옵션을 추가하여, 이 옵션으로 CSQL을 실행한 dba는 슬레이브 DB 또는 레플리카 DB에 직접 접속하여 쓰기가 가능하게 되었다. 단, 레플리카에 직접 쓰는 데이터는 복제되지 않는다. 이 옵션은 시스템 관리자 모드 옵션(--sysadm)과 함께 사용해야 한다.

csql --sysadm --write-on-standby -u dba testdb

슬레이브 노드 또는 레플리카 노드에서 CSQL로 통계 정보 갱신이 가능해짐 (CUBRIDSUS-12198)

CSQL에 --sysadm과 함께 --write-on-standby 옵션을 사용하면 슬레이브 노드 또는 레플리카 노드에서 UPDATE STATISTICS 문의 수행이 가능해졌다.

CAS와 DB 서버 간 복제 지연 시 다른 노드로 재접속을 시도하게 하는 기능 추가 (CUBRIDSUS-11707)

cubrid_ha.conf에 ha_delay_limit와 ha_delay_limit_delta를 추가하여 standby 서버에 ha_delay_limit 이상의 복제 지연 발생 시 CAS는 해당 DB와 연결을 끊고 다른 DB로 접속을 시도하는 기능을 추가했다. ha_delay_limit 이상의 복제 지연 발생 시 서버는 스스로 복제 지연 상태라 판단하고 복제 지연 시간이 ha_delay_limit에서 ha_delay_limit_delta를 뺀 시간 보다 낮아질 경우 복제 지연이 해소되었다고 판단한다.

복제 지연으로 인해 우선 순위가 낮은 DB에서 연결된 CAS는 cubrid_broker.conf의 RECONNECT_TIME으로 명시한 시간이 경과하면 복제 지연이 해소되었을 것으로 기대하여, 우선 순위가 높은 standby DB 서버에 재접속을 시도한다.

"cubrid statdump" 명령 수행 시 출력되는 결과에 복제 지연 시간을 추가 (CUBRIDSUS-12152)

"cubrid statdump" 명령 수행 시 출력되는 복제 지연 시간의 항목 이름은 "Time_ha_replication_delay"이다. (단위: 초)

복제 반영 시간을 단축시키는 유틸리티 추가 (CUBRIDSUS-12813)

새로 추가된 "cubrid heartbeat prefetchlogdb" 명령을 수행하면 applylogdb 프로세스가 반영해야 할 데이터를 미리 읽어서(prefetch) 데이터베이스 버퍼에 로딩하므로, applylogdb 프로세스가 반영해야 할 데이터를 데이터베이스 볼륨(디스크)으로부터 읽어들이는 시간이 불필요하게 된다.

applylogdb 프로세스가 받는 SQL에 대한 로깅 기능 추가 (CUBRIDSUS-11299)

"ha_enable_sql_logging" 파라미터의 값이 yes이면 해당 로그 파일이 기록되며, 파일의 크기가 "ha_sql_log_max_size_in_mbytes" 파라미터의 값을 초과하면 새로운 로그 파일이 생성된다.

copylogdb의 지연으로 인해 로그 플러시도 지연되는 상태를 감지하여 데이터베이스 서버 로그 파일에 로깅하는 기능 추가 (CUBRIDSUS-13232)

cubrid.conf의 log_trace_flush_time 파라미터에 설정한 시간보다 로그 플러싱 시간이 오래 걸리는 상태를 감지하여 로깅하는 기능을 추가했다.

운영 편의성

SHARD proxy 내부에서 발생하는 에러를 확인할 수 있도록 상태 정보 강화 (CUBRIDSUS-12204)

SHARD proxy 상태 정보 항목들을 추가하고, shard proxy의 에러 회수도 확인할 수 있도록 수정했다. "cubrid broker status" 명령에서 변경 또는 추가된 옵션은 다음과 같다.

옵션 구분 설명
-b 변경 shard proxy에서 에러가 발생한 경우에도 ERR-Q 항목의 값이 증가한다. 수정 이전 버전에서는 proxy 내에서 에러가 발생하는 경우 에러 개수가 증가되지 않는다.
-c 변경 CUR_CLIENT 항목이 추가로 출력된다. 해당 proxy에 접속되어 있는 응용 클라이언트 개수를 출력한다.
-S 추가 -b 옵션의 내용을 각 shard DB 별로 구분하여 출력한다. -b 옵션에서 NAME, PID, PORT, JQ, #CONNECT를 제외한 나머지 항목과 SHARD_ID, SHARD-Q, #REQUEST를 추가로 출력한다.
-P 추가 -b 옵션의 내용을 각 proxy 별로 구분하여 출력한다. -b 옵션에서 NAME, PID, PORT, JQ를 제외한 나머지 항목과 PROXY_ID, SHARD-Q, #RESTART를 추가로 출력한다.
-P -f 추가 -P 옵션에서 출력하는 항목에 STMT-POOL-RATIO 항목을 추가로 출력한다. 이 항목은 prepare statement 사용 시 pool에서 statement를 사용하는 비율을 나타낸다.

보다 자세한 내용은 매뉴얼의 CUBRID SHARD 설명을 참고한다.

DB에 지정한 질의가 정상 수행되는지 테스트해 보는 명령 추가 (CUBRIDSUS-12094)

DB에 질의 수행을 테스트해 보고 성공 여부를 출력하는 명령을 추가했다. 질의 수행 후 트랜잭션은 롤백된다. SHARD 기능이 설정된 경우, 모든 SHARD DB에 질의를 수행해 볼 수 있다. 이 명령어를 통해 DB 연결 상태, 사용자의 질의 권한, SHARD DB의 해싱 결과 등을 확인할 수 있다.

cubrid broker test <broker_name> [-D <db_name>] [-u <db_user>] [-p <db_password>] {-c <query> | -i <input_file>} [-o <output_file>] [-s] [-v]

다음은 사용 예이다.

  • DB에 질의

    cubrid_broker.conf의 SHARD 파라미터 값이 OFF일 때

    $ cubrid broker test shard1 -D shard -u shard -p shard123 -c "select 1 from db_root where charset = 3"
    
    @ cubrid broker test
    @ [OK] CONNECT broker1 DB [demodb] USER [shard]
    
    @ SHARD OFF
    
    RESULT         ROW COUNT      EXECUTION TIME      QUERY
    ========================================================
    OK             1              0.011341 sec        select 1,'a' from db_root where charset = 3
    @ [OK] QUERY TEST
    

    cubrid_broker.conf의 SHARD 파라미터 값이 ON일 때

    $ cubrid broker test shard1 -D shard -u shard -p shard123 -c "select 1 from db_root where charset = 3"
    
    @ cubrid broker test
    @ [OK] CONNECT shard1 DB [shard] USER [shard]
    
    @ SHARD ON
    
    RESULT         SHARD_ID  ROW COUNT      EXECUTION TIME      QUERY
    ==================================================================
    OK             0         1              0.003436 sec        select 1 from db_root where charset = 3
    OK             1         1              0.003010 sec        select 1 from db_root where charset = 3
    OK             2         1              0.003039 sec        select 1 from db_root where charset = 3
    OK             3         1              0.002916 sec        select 1 from db_root where charset = 3
    @ [OK] QUERY TEST
    
  • 사용자 권한 확인

    SHARD DB 중 하나에 INSERT 권한이 없는 경우

    $ cubrid broker test shard1 -c "insert into foo values (1,"a") " -v
    
    @ cubrid broker test
    @ [OK] CONNECT shard1 DB [shard] USER [shard]
    
    @ SHARD ON
    
    RESULT         SHARD_ID  ROW COUNT      EXECUTION TIME      QUERY
    ==================================================================
    OK             0         1              0.001322 sec        insert into foo values(1,'a')
    FAIL(-494)     -1        -1             0.001608 sec        insert into foo values(1,'a')
    <Error>
    ERROR CODE : -494
    Semantic: INSERT is not authorized on foo. insert into foo foo (foo.a, foo.b) values (1,  cast('a' as v...[CAS INFO - 127.0.0.1:52002, 1, 18145].
    
    OK             2         1              0.001334 sec        insert into foo values(1,'a')
    OK             3         1              0.001325 sec        insert into foo values(1,'a')
    @ [FAIL] QUERY TEST
    

    SHARD DB 중 하나에 UPDATE 권한이 없는 경우

    $ vi dml.txt
    
    #query
    select a from foo
    insert into foo(b) values(3)
    update foo set c = 2 where b = 3
    delete foo where b = 3
    
    $ cubrid broker test broker1 -D demodb -u shard -p shard123 -i dml.txt -v
    
    @ cubrid broker test
    @ [OK] CONNECT broker1 DB [demodb] USER [shard]
    
    @ SHARD OFF
    
    RESULT         ROW COUNT      EXECUTION TIME      QUERY
    ========================================================
    OK             1              0.001612 sec        select a from foo
    <Result of SELECT Command>
      a
    ------------
      1
    
    OK             1              0.001215 sec        insert into foo(b) values(3)
    FAIL(-494)     -1             0.001291 sec        update foo set c = 2 where b = 3
    <Error>
    ERROR CODE : -494
    Semantic: UPDATE is not authorized on foo. update foo foo set foo.c=2 where foo.b=3[CAS INFO - 127.0.0.1:52001, 1, 18139].
    
    OK             0              0.001534 sec        delete foo where b = 3
    @ [FAIL] QUERY TEST
    
  • SHARD HASH 정상 동작 확인

    $ vi test_query.txt
    
    #query
    select number from demo_db where key = /*+ shard_key */ 14
    select number from demo_db where key = /*+ shard_key */ 50
    select number from demo_db where key = /*+ shard_key */ 80
    select number from demo_db where key = /*+ shard_key */ 120
    ..
    
    $ cubrid broker test shard1 -D shard -u shard -p shard123 -i shard_key.txt -v -s
    
    @ cubrid broker test
    @ [OK] CONNECT shard1 DB [shard] USER [shard]
    
    @ SHARD ON
    
    RESULT         SHARD_ID  ROW COUNT      EXECUTION TIME      QUERY
    ==================================================================
    OK             0         1              0.002225 sec        select * from foo where a = /*+ shard_key */ 10
    <Result of SELECT Command>
      a           b
    ----------------------------------
      10          'aaaa'
    
    OK             1         1              0.001870 sec        select * from foo where a = /*+ shard_key */ 40
    <Result of SELECT Command>
      a           b
    ----------------------------------
      40          'bbb'
    
    OK             2         1              0.002004 sec        select * from foo where a = /*+ shard_key */ 70
    <Result of SELECT Command>
      a           b
    ----------------------------------
      70          'cccc'
    
    OK             3         1              0.002025 sec        select * from foo where a = /*+ shard_key */ 100
    <Result of SELECT Command>
      a           b
    ----------------------------------
      100         'dddd'
    
    @ [OK] QUERY TEST
    

설정

cubrid.conf에 standalone 섹션 추가 (CUBRIDSUS-12670)

SA-mode(cubrid start -S)로 cubrid 유틸리티를 구동할 때에만 특정 파라미터가 적용되도록 cubrid.conf에 standalone 섹션을 추가했다.

cubrid.conf

.....
[common]
.....
sort_buffer_size=2M
.....
[standalone]

sort_buffer_size=256M
.....

예를 들어, 위와 같이 설정한 상태에서 --CS-mode로 DB를 구동하면 "sort_buffer_size=2M"가 적용된다. 하지만 DB를 정지하고 "cubrid loaddb --SA-mode"를 실행할 때에는 "sort_buffer_size=256M"가 적용된다.

databases.txt의 db-host에 명시된 호스트들 중 접속을 시도할 복제 지연 호스트들의 개수를 명시하는 파라미터 추가 (CUBRIDSUS-12495)

새로 추가된 MAX_NUM_DELAYED_HOSTS_LOOKUP 파라미터는 databases.txt의 db-host에 명시된 호스트들에 접속을 시도할 때, 접속을 시도하는 복제 지연 호스트 개수를 제한한다. 단, PREFERRED_HOSTS에는 적용되지 않는다. 이 파라미터에서 지정한 개수까지 복제 지연이 발생하면 나머지 호스트들도 복제 지연일 것이라고 가정하기 때문에, 브로커는 더 이상 복제 지연이 아닌 호스트 찾기를 포기하고 가장 마지막에 찾은 복제 지연 서버와 연결한다.

유틸리티

질의 수행 시간 및 질의 계획을 재확인하기 위해 SQL 로그를 재생하는 cubrid_replay 유틸리티 추가 (CUBRIDSUS-13170)

이 유틸리티를 통해 다음 정보를 확인할 수 있다.

  • SQL 로그에 기록된 질의 수행 시간과 이 유틸리티에 의해 재생된 질의 수행 시간의 차이가 큰 것부터 순서대로 확인할 수 있다. 즉, 어떤 장비에 기록된 SQL 로그를 다른 장비에서 재생하여 어떤 SQL에서 성능 차이가 발생하는지를 확인할 수 있다.
  • SELECT 문 뿐 아니라 UPDATE, DELETE 문도 SELECT 문으로 변환하여 질의 계획을 확인할 수 있다.

브로커의 ACL 리스트에 등록된 IP마다 해당 IP에서 수행된 클라이언트의 최종 접속 시간을 출력하는 기능 및 ACL REJECT 횟수를 출력하는 기능 추가 (CUBRIDSUS-12469)

  1. 브로커의 ACL 리스트에 등록된 IP마다 해당 IP에서 수행된 클라이언트의 최종 접속 시간을 출력한다.

    $ cubrid broker acl status
    ACCESS_CONTROL=ON
    ACCESS_CONTROL_FILE=access_file.txt
    
    [%broker1]
    demodb:dba:iplist1.txt
           CLIENT IP LAST ACCESS TIME
    ==========================================
        10.20.129.11
      10.113.153.144 2013-11-07 15:19:14
      10.113.153.145
      10.113.153.146
             10.64.* 2013-11-07 15:20:50
    
    testdb:dba:iplist2.txt
           CLIENT IP LAST ACCESS TIME
    ==========================================
                   * 2013-11-08 10:10:12
    
  2. broker status에 ACL REJECT 횟수(#REJECT)를 출력한다.

    $ cubrid broker status -b -f
    @ cubrid broker status
      NAME    PID   PSIZE PORT  AS(T W B 1s-W 1s-B) JQ TPS QPS LONG-T LONG-Q ERR-Q UNIQUE-ERR-Q CANCELED ACCESS_MODE SQL_LOG #CONNECT #REJECT
    ==========================================================================================================================================
    * broker1 16265 93380 55300    0 0 0 0    0     0  4   0   0/60.0 0/60.0 0     0            0        RW          ALL     4        1
    

"cubrid statdump" 명령 출력 시 질의 계획 캐시 정보 추가 (CUBRIDSUS-12774)

추가된 정보는 다음과 같다.

이름 설명
Num_plan_cache_add 캐시 엔트리(entry)가 새로 추가된 횟수
Num_plan_cache_lookup 특정 key를 사용하여 lookup을 시도한 횟수
Num_plan_cache_hit 질의 문자열 해시 테이블에서 엔트리를 찾은(hit) 횟수
Num_plan_cache_miss 질의 문자열 해시 테이블에서 엔트리를 찾지 못한(miss) 횟수
Num_plan_cache_full 캐시 엔트리의 개수가 허용된 최대 개수를 넘어 희생자(victim) 탐색을 시도한 횟수
Num_plan_cache_delete 캐시 엔트리가 삭제된(victimized) 횟수
Num_plan_cache_invalid_xasl_id xasl_id 해시 테이블에서 엔트리를 찾지 못한(miss) 횟수. 서버에서 특정 엔트리가 제거(victimize)되었는데, 해당 엔트리를 클라이언트에서 요청했을 때 발생하는 에러 횟수
Num_plan_cache_query_string_hash_entries 질의 문자열 해시 테이블의 현재 엔트리 개수
Num_plan_cache_xasl_id_hash_entries xasl id 해시 테이블의 현재 엔트리 개수
Num_plan_cache_class_oid_hash_entries class oid 해시 테이블의 현재 엔트리 개수

"cubrid unloaddb" 명령에 DB 계정과 암호를 지정하는 옵션 추가 (CUBRIDSUS-12070)

수정 이전 버전에서는 DB 계정과 암호의 지정이 없이 "cubrid unloaddb"를 수행할 수 있어 전체 데이터를 덤프할 수 있는 보안 문제가 존재했으나, "cubrid unloaddb"에 DB 계정과 암호를 지정해야만 수행 가능하도록 수정했다. 수정 이후 버전에서 DB 계정과 암호가 지정되지 않을 경우 DB 계정은 "DBA", 암호는 빈 문자열("")이 된다.

cubrid 유틸리티 수행 결과에 대한 로깅 기능 추가 (CUBRIDSUS-11676)

cubrid 유틸리티를 통해 수행되는 프로세스들의 수행 결과에 대한 로깅 기능을 추가했다. $CUBRID/log/cubrid_utility.log 파일에 다음과 같이 출력된다.

13-11-19 15:27:19.426 (17724) cubrid manager stop
13-11-19 15:27:19.430 (17724) FAILURE: ++ cubrid manager server is not running.
13-11-19 15:27:19.434 (17726) cubrid service start
13-11-19 15:27:19.439 (17726) FAILURE: ++ cubrid master is running.
13-11-19 15:27:22.931 (17726) SUCCESS
13-11-19 15:27:22.936 (17756) cubrid service restart
13-11-19 15:27:31.667 (17756) SUCCESS
13-11-19 15:27:31.671 (17868) cubrid service stop
13-11-19 15:27:34.909 (17868) SUCCESS

Windows 환경에서는 서비스 프로세스를 통해 수행되는 프로세스는 오류 메시지를 출력하지 못하므로, 수정 이후 버전부터 서비스 구동과 관련된 오류메시지는 cubrid_utility.log를 통해 확인할 수 있다.

드라이버

[JDBC] 연결 객체 생성 시 브로커 연결 없이 대기하게 하는 기능 추가 (CUBRIDSUS-13376)

JDBC 연결 URL의 속성에 'useLazyConnection=(true|false)'를 추가했다. 기본값은 false이며, 이 값이 true이면 사용자의 연결 요청 시 브로커 연결 없이 성공을 반환하며, prepare나 execute 등의 함수를 호출할 때 브로커에 연결된다. 이 값을 true로 설정하면 많은 클라이언트 응용이 동시에 재시작되면서 CONNECTION POOL을 생성할 때 접속이 지연되거나 실패하는 현상을 피할 수 있다.

[CCI] 로그인 타임아웃 값 변경 함수 추가 및 datasource 속성 변경 함수 추가 (CUBRIDSUS-12530)

다음 함수들이 추가되었다.

  • cci_set_login_timeout()

    로그인 타임아웃을 밀리초 단위로 설정한다.

  • cci_get_login_timeout()

    로그인 타임아웃 값을 반환한다.

  • cci_datasource_change_property()

    CCI의 DATASOURCE에 대해 key에 명시한 속성(property)의 값을 value에 설정한다. 이 함수를 사용하여 변경한 속성 값은 datasource 내 모든 연결에 적용된다.

[CCI] 문자열 중간에 '\0'가 있는 경우에도 바인딩할 수 있는 cci_bind_param_ex() 추가 (CUBRIDSUS-9791)

cci_bind_param()은 중간에 '\0'이 포함된 문자열을 바인딩할 수 없으므로, 이 동작이 가능한 cci_bind_param_ex()를 추가했다.

cci_bind_param_ex(statement, 1, CCI_A_TYPE_STR, "aaa\0bbb", 7, CCI_U_TYPE_STRING, 0);

위에서 다섯번째 인자인 7이 문자열의 바이트 길이에 해당된다.

성능 향상

SQL

통계 정보 갱신 시 샘플링 방식 도입과 함께 NO_STAT 힌트가 무시되도록 수정 (CUBRIDSUS-12395)

통계 정보 갱신 시 샘플링 방식을 도입하여 통계 정보 갱신 시간이 단축되었다. 수정 이후 "UPDATE STATISTICS" 문 뒤에 "WITH FULLSCAN" 구문이 없으면 샘플링된 데이터를 가지고 통계 정보를 업데이트하며, "WITH FULLSCAN"을 추가하면 전체 데이터를 가지고 통계 정보를 업데이트한다.

UPDATE STATISTICS ON foo;
UPDATE STATISTICS ON foo WITH FULLSCAN;

샘플링 방식의 도입으로 통계 정보 갱신에 대한 부담이 줄게 되어 NO_STATS 힌트의 사용 또한 불필요하게 되었다. 따라서 NO_STATS 힌트를 입력하더라도 이를 무시하도록 수정했다.

Loose Index Scan 지원 (CUBRIDSUS-9024)

인덱스 서브 키 각각의 고유(unique) 값에 대해 동적으로 범위를 조정하여 B 트리 검색을 재시작하는 loose index scan을 지원한다. 따라서 B 트리의 스캔 영역을 상당 부분 줄일 수 있다.

loose index scan은 INDEX_LS 힌트를 부여하고 다음의 경우를 만족하는 경우 loose index scan의 적용이 고려된다.

  1. 인덱스가 SELECT 리스트의 모든 부분을 커버하는 경우. 즉, 커버링 인덱스가 적용되는 경우
  2. SELECT DISTINCT, SELECT ... GROUP BY 또는 단일 투플 SELECT 문인 경우
  3. MIN/MAX 함수를 제외한 모든 집계 함수가 DISTINCT를 포함하는 경우
  4. COUNT(*)가 사용되어선 안 됨
  5. 부분 키(subkey)의 카디널리티(고유 값의 개수)가 전체 인덱스의 카디널리티보다 100배 작은 경우

loose index scan이 가능한 질의의 예는 다음과 같다.

CREATE TABLE tbl1 (
    k1 INT,
    k2 INT,
    k3 INT,
    k4 INT
);

INSERT INTO tbl1
SELECT ROWNUM MOD 2, ROWNUM MOD 400, ROWNUM MOD 80000, ROWNUM
FROM db_class a, db_class b, db_class c, db_class d, db_class e LIMIT 360000;

CREATE INDEX idx ON tbl1 (k1, k2, k3);
UPDATE STATISTICS ON tbl1;

-- Q1
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1, k2
FROM tbl1
WHERE k1 >= 0 AND k1 <= 1 AND k2 > 3 AND k2 < 11;

-- Q2
SELECT /*+ RECOMPILE INDEX_LS */ k1, SUM(DISTINCT k2)
FROM tbl1
WHERE k1 > -10000 GROUP BY k1;

-- Q3
SELECT /*+ RECOMPILE INDEX_LS */ SUM(DISTINCT k1), SUM(DISTINCT k2)
FROM tbl1;

Q2에서 "k1 > -10000" 조건을 명시한 이유는 loose index scan을 가능하게 하기 위한 것이다. CUBRID는 NULL 값을 인덱스에서 검색할 수 없기 때문에 인덱스 스캔을 하려면 부분 키(subkey)를 사용할 수 있게 하는 WHERE 조건이 반드시 필요하다.

인덱스 스킵 스캔 힌트 추가 (CUBRIDSUS-13348)

인덱스 스킵 스캔의 적용 여부를 통계 정보에 의해 결정하는 경우 사용자의 의도에 맞지 않게 순차 스캔(sequential scan)이 적용될 수 있으므로, 인덱스 스킵 스캔 힌트(INDEX_SS)를 추가하여 해당 힌트를 입력하는 경우에만 인덱스 스킵 스캔이 적용될 수 있도록 수정했다.

집계 함수와 GROUP BY 절을 포함하며 커버링 인덱스가 적용되는 질의에서 GROUP BY 절 최적화(skip group by)에 의한 인덱스 스킵 스캔이 적용되도록 수정 (CUBRIDSUS-7508)

CREATE TABLE tab (k1 int, k2 int, k3 int, v double);
INSERT INTO tab
SELECT
    RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 5,
    RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 10,
    RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 100000,
    RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 100000
FROM db_class a, db_class b, db_class c, db_class d LIMIT 20000;
CREATE INDEX idx ON tab(k1, k2, k3);

SELECT /*+ RECOMPILE INDEX_SS */ k1, k2, SUM(DISTINCT k3)
FROM tab
WHERE k2 > -1
GROUP BY k1, k2;

위의 SELECT 질의 수행 시 GROUP BY 최적화가 적용된다.

버퍼 매니저의 페이지 교체 알고리즘 개선 (CUBRIDSUS-12347)

버퍼 관리자에 scan resistant 버퍼 관리 기법을 탑재하였다. 이로 인해 큰 스캔으로 인한 버퍼의 hit ratio 및 성능 저하가 개선되었다. 연속된 스캔을 포함하는 질의에 대해 YCSB 테스트를 수행한 결과, SELECT 작업에 대해 1.9%, SCAN 작업에 대해 4.6%가 향상되었다.

한 분석 함수의 OVER ... PARTITION BY 또는 ORDER BY 절의 칼럼이 다른 분석 함수의 해당 절의 칼럼에 포함되면 최적화가 가능하도록 수정 (CUBRIDSUS-12452)

수정 이전에는 한 분석 함수의 OVER ... PARTITION BY 또는 ORDER BY 절의 칼럼들이 동일해야만 최적화가 가능했으나, 한 분석 함수의 해당 절의 칼럼들이 다른 분석 함수의 해당 절의 칼럼들에 포함되어도 최적화가 가능하도록 수정했다.

여기에서 최적화란 계산에 필요한 투플의 스캔 회수가 한 번으로 줄어드는 것을 말한다.

-- Q1
SELECT
SUM (v) OVER (PARTITION BY k1) AS a1,
AVG (v) OVER (PARTITION BY k1) AS a2
FROM tbl;

-- Q2
SELECT
SUM (v)          OVER (ORDER BY k1) AS a1,
AVG (v)          OVER (ORDER BY k1, k2) AS a2,
STDDEV_SAMP (v)  OVER (ORDER BY k1, k2, k3) AS a3,
STDDEV_POP (v)   OVER (ORDER BY k1, k2, k3, k4) AS a4,
VAR_SAMP (v)     OVER (PARTITION BY k1) AS a5,
VAR_POP (v)      OVER (PARTITION BY k2, k1) AS a6,
MIN (v)          OVER (PARTITION BY k3, k2, k1) AS a7,
MAX (v)          OVER (PARTITION BY k3, k2, k1, k4) AS a8,
LEAD (v)         OVER () AS a9
FROM tbl;

Q1의 경우 수정 이전과 이후 모두 최적화가 가능하지만, Q2의 경우 수정된 버전에서만 최적화가 가능하다.

LIKE 질의의 검색 성능 개선 (CUBRIDSUS-10597)

2008 R4.4 버전 대비 퇴행된 LIKE 질의의 검색 성능을 개선했다.

분할 테이블에서 집계 함수 성능 최적화 (CUBRIDSUS-10794)

분할 테이블에서 COUNT(*), COUNT(column), MIN 그리고 MAX 함수를 계산할 때 각 분할 테이블 별로 집계하여 합산하는 방식을 적용하여 성능이 최적화되도록 개선했다.

집계 함수를 포함하는 질의의 수행 성능 개선 (CUBRIDSUS-11399)

집계 함수를 포함하는 질의 수행 시 해시를 이용한 그룹핑을 적용하여 수행 성능을 개선했다. 이와 함께 해싱 결과를 저장하는 공간의 크기를 지정하는 max_agg_hash_size, 해싱 결과대로 정렬할 것인지 여부를 지정하는 agg_hash_respect_order 파라미터가 추가되었다.

기본 키 또는 고유 키를 포함하는 조건이 있으면 다른 키가 아닌 해당 키를 선택하여 스캔 범위를 좁히도록 수정 (CUBRIDSUS-12615)

기본 키 또는 고유 키의 모든 칼럼에 대해 동등(equal)조건이 주어지는 경우, 해당 키를 사용하는 스캔 계획이 생성되도록 수정했다.

CREATE TABLE foo (a INT, b INT, c STRING);
CREATE UNIQUE INDEX u_foo ON foo(a);
CREATE INDEX i_foo ON foo(b, c);

SELECT /*+ RECOMPILE */ b, c
FROM foo
WHERE a = 100 AND b = 100 AND c = 'aaaaa';

INSERT 문의 수행 성능 개선 (CUBRIDSUS-12778)

INSERT ... DEFAULT, INSERT ... VALUES, INSERT ... SELECT, REPLACE, INSERT ... ON DUPLICATE KEY UPDATE 등의 구문에서 INSERT 연산 수행 시 수행 성능을 개선하여 시험한 결과, 1~10% 정도가 향상되었다.

단, 해당 테이블에 INSERT 트리거가 존재하는 경우 기존 버전과 같은 성능을 나타낸다.

UPDATE 문에 대한 복제 성능 개선 (CUBRIDSUS-12772)

UPDATE 문에 대한 복제 성능이 기존 대비 2배 정도 향상되었다.

테이블에 대해 다량의 DELETE가 수행되어 데이터 페이지에 빈 공간이 늘어난 이후, INSERT 수행에 많은 시간이 소요됨 (CUBRIDSUS-12405)

하나의 테이블에 대해 많은 양의 DELETE가 발생해서 데이터 페이지에 대한 빈 공간이 늘어난 이후, 여러 클라이언트들이 해당 테이블에 대해 동시에 INSERT를 수행할 때 비정상적으로 많은 시간이 소요되는 현상을 수정했다.

질의 계획 캐시에 설정한 제한 개수보다 많은 계획이 저장됨 (CUBRIDSUS-12660)

cubrid.conf의 max_plan_cache_entries 파라미터를 통해 질의 계획 캐시에 설정한 제한 개수보다 많은 계획이 저장되는 현상을 수정했다.

동시에 같은 테이블에 많은 FULL SCAN 작업이 수행되는 경우에 대해 성능을 일부 개선 (CUBRIDSUS-13188)

테이블 FULL SCAN 질의가 수행되면 INSERT에서 사용될 BEST PAGE를 질의 처리와 병행하여 선별하게 되는데, 이때 다른 트랜잭션이 DELETE 작업 이후 COMMIT을 수행하지 않아 비어있지만 사용할 수 없는 공간을 확인하는 과정을 수행한다. 그런데 이 과정에서 CRITICAL SECTION을 사용하므로 동시에 많은 FULL SCAN 질의는 성능 저하를 유발한다. 실제 INSERT 과정에서 이 공간을 다시 확인하게 되므로, 이 수정에서는 DELETE후 COMMIT하지 않은 공간을 확인하는 절차를 생략하여 CRITICAL SECTION으로 인한 병목 현상을 줄이도록 했다.

Sharding

SHARD의 statement pool에서 statement가 재사용될 때의 성능 개선 (CUBRIDSUS-12095)

statement pool에서 statement가 재사용될 때의 성능을 개선했다.

또한, SHARD_MAX_PREPARED_STMT_COUNT의 기본값을 2000에서 10000으로 늘렸다.

기타

응용 프로그램에서 한 번에 여러 개의 연결을 만드는데 걸리는 시간을 줄임 (CUBRIDSUS-7491)

한 번에 여러 개의 연결을 만드는 예로 연결 풀(connection pool)을 생성하는 경우가 있다.

Windows 환경에서 응용프로그램을 통해 질의를 수행하는 경우 성능 개선 (CUBRIDSUS-12980)

Windows 환경에서 응용 프로그램의 드라이버와 CAS 사이의 데이터 전송 지연 문제로 인해 Linux 환경에 비해 질의 수행이 상대적으로 느린 문제를 개선했다.

동작 변경

SQL

SELECT 리스트 표현식 안의 칼럼과 표현식의 별칭(alias)이 GROUP BY 절의 칼럼 이름과 일치하는 경우의 동작 변경 (CUBRIDSUS-13226)

CREATE TABLE t1(a INT, b INT, c INT);
INSERT INTO t1 VALUES(1,1,1);
INSERT INTO t1 VALUES(2,NULL,2);
INSERT INTO t1 VALUES(2,2,2);

SELECT a, NVL(b,2) AS b
FROM t1
GROUP BY a, b; -- Q1

위의 SELECT 질의를 수행할 때 GROUP BY a, b는

  • 9.2 이하 버전에서 GROUP BY a, NVL(b, 2) (별칭 이름 b)로 해석되며, 아래 Q2와 동일한 결과를 출력한다.

    SELECT a, NVL(b,2) AS bxxx
    FROM t1
    GROUP BY a, bxxx; -- Q2
    
            a b
    ======================
            1 1
            2 2
    
  • 9.3 이상 버전에서 GROUP BY a, b (칼럼 이름 b)로 해석되며, 아래 Q3와 동일한 결과를 출력한다.

    SELECT a, NVL(b,2) AS bxxx
    FROM t1
    GROUP BY a, b; -- Q3
    
            a b
    ======================
            1 1
            2 2
            2 2
    

정렬 병합 조인(sort merge join) 실행 계획을 생성하지 않도록 수정(CUBRIDSUS-13186)

SELECT /*+ USE_MERGE */  DISTINCT h.host_year, o.host_nation
FROM history h LEFT OUTER JOIN olympic o
ON h.host_year = o.host_year AND o.host_year > 1950;

단, USE_MERGE 힌트를 명시하거나 cubrid.conf의 optimizer_enable_merge_join 값을 yes로 설정하면 정렬 병합 조인(sort merge join) 계획이 질의 계획 후보에 포함될 수 있다.

HA

"cubrid heartbeat reload" 명령 수행 시 노드 정보만 "reload"하도록 수정 (CUBRIDSUS-12679)

해당 명령 수행 시 수정 이전에는 추가된 노드의 HA 프로세스 구동, 삭제된 노드의 HA 프로세스 정지가 자동으로 수행되었으나, 수정 이후 노드 정보만 변경된다.

노드 정보가 변경된 이후 HA 프로세스의 구동/정지는 9.3에서 새로 추가된 아래의 "cubrid heartbeat replication start/stop <node_name>" 명령을 사용한다.

"cubrid heartbeat replication start/stop <node_name>" 명령 추가 (CUBRIDSUS-12679)

특정 노드에 대해 HA 프로세스를 시작/정지하는 명령을 추가했다. 일반적으로 "cubrid heartbeat reload" 명령을 수행한 이후 추가/삭제된 노드의 HA 프로세스를 일괄적으로 시작/정지하기 위해 실행한다.

드라이버

[JDBC][CCI] CCI의 loginTimeout과 JDBC의 connectTimeout의 적용 범위 및 기본값 변경 (CUBRIDSUS-12537)

수정 이전 버전에서는 URL에 설정한 CCI의 loginTimeout(JDBC는 ConnectTimeout)이 최초 접속 시에만 적용되며 loginTimeout(JDBC는 connectTimeout)을 지정하지 않으면 무한 대기한다. 수정 이후 로그인 타임아웃이 최초 접속 이후 내부 재접속(EXECUTE 함수 수행 도중 발생 가능)에도 적용되며, loginTimeout(JDBC는 connectTimeout)을 지정하지 않은 경우 기본 값이 30초로 설정된다.

[JDBC][CCI] 트랜잭션 수행 도중 서버 프로세스가 재시작되거나 HA 환경에서 절체(failover)가 발생한 경우, 커밋이나 롤백의 명시없이 이어서 실행하는 질의는 에러로 처리하도록 수정 (CUBRIDSUS-13276)

수정 이전 버전에서는 트랜잭션 수행 도중 DB 서버 재시작 또는 HA 절체로 인해 에러가 발생하면 트랜잭션이 롤백되고 내부적으로 DB 서버에 재접속되며, 커밋이나 롤백의 명시가 없더라도 이어서 실행하려는 질의는 새로운 트랜잭션의 질의로 판단되어 정상 수행된다.

수정된 버전에서는 트랜잭션 수행 도중 DB 서버 재시작 또는 HA 절체로 인해 에러가 발생하면, 사용자가 커밋 혹은 롤백을 명시하지 않고 이어서 실행하려는 질의는 이전 트랜잭션의 연속된 질의로 판단되어 에러로 처리된다.

[JDBC] 연결 객체에 사용자 이름 또는 암호를 ""로 입력할 때 연결 URL의 사용자 또는 암호를 따르도록 수정(CUBRIDSUS-12588)

JDBC 연결 객체의 사용자 또는 암호에 빈 문자열("")을 입력할 때 JDBC 메서드의 동작을 CCI 함수의 동작과 동일하게 연결 URL의 사용자 또는 암호를 따르도록 수정했다.

cci_connect_with_url ("cci:cubrid:localhost:3300:demodb:dba::", "", "")
-- In C API
SELECT CURRENT_USER();
dba@localhost
DriverManager.getConnection("jdbc:cubrid:localhost:3300:demodb:dba::", "", "")
SELECT CURRENT_USER();

-- In JDBC, before change
public@localhost

-- In JDBC, after change
dba@localhost

설정

브로커 접속 로그(ACCESS_LOG) 파일의 출력 정보 및 관련 파라미터 수정 (CUBRIDSUS-12600)

ACCESS LOG 파일의 로깅 형식과 로그 파일 백업 정책이 변경되었다. 상세한 수정 내용은 다음과 같다.

  1. cubrid_broker.conf의 ACCESS_LOG 기본값을 OFF로 변경했다.

  2. ACCESS_LOG 파일에 접속 정보만 기록하도록 수정했다.

  3. 접속 거부된 기록은 broker_name.access.denied에 기록된다. ACCESS_LOG 파일과 동일한 규칙으로 백업된다.

    다음은 수정 이후 접속 정보이다.

    1 127.0.0.1 2013/07/19 16:25:46 tdb dba NEW 49463
    

    위의 접속 정보에서 뒤의 2개 필드는 다음을 의미한다.

    • connection_type: NEW ,OLD, REJ 중 하나의 값을 가지며 각각 다음을 의미한다.

      • NEW: 새로운 접속
      • OLD: change client 또는 CAS 재시작으로 인한 기존 연결의 재접속
      • REJ: 접속 거부(access.denied 파일에만 기록됨)
    • session-id: 서버에서 할당한 세션 번호

      change client 등으로 인해 CAS번호가 변경되었을 때, 최초 연결이 어떤 CAS에 다시 접속되었는지 추적할 수 있도록 한다.

  4. 브로커 동작 중 동적으로 변경 가능한 ACCESS_LOG_MAX_SIZE 파라미터를 추가했다. ACCESS_LOG 파일의 최대 크기를 지정하며, ACCESS_LOG 파일이 지정한 크기보다 커지면 broker_name.access.YYYYMMDDHHMISS 형식의 이름으로 백업된 후 새 파일(broker_name.access)에 로그가 기록된다. 기본값은 10M 이며 최대 2G 까지 설정이 가능하다.

  5. ACCESS_LOG_DIR 파라미터를 추가했다. ACCESS_LOG 파일이 생성되는 디렉터리를 지정한다. 기본값은 log/broker 이다.

  6. 수정 이전 버전에서는 브로커 정지 시 ACCESS_LOG가 지워지거나 백업되었으나, 수정 이후 브로커 정지 시 ACCESS_LOG와 관련하여 아무것도 하지 않는다. 이와 함께, LOG_BACKUP 파라미터는 더 이상 사용되지 않는다.

유틸리티

"cubrid broker status" 명령에 "-b" 또는 "-f" 옵션 사용 시 출력되는 값들이 잘림 (CUBRIDSUS-13588)

수정 이전에는 브로커 이름이 영문 최대 20자를 넘으면 넘는 부분을 생략하여 출력했으나 수정 이후에는 생략 없이 전체 이름을 출력한다. 또한, "LONG-T "등 고정폭을 넘어 출력되는 값은 잘려서 출력되었으나 값이 잘리지 않도록 수정했다.

이 수정으로 인해 출력되는 값의 문자열 길이에 따라 출력폭이 가변적일 수 있음에 유의한다.

개선 및 오류 수정

리소스

페이지 크기에 근접한 크기의 레코드에 대해 INSERT/DELETE 작업이 반복되는 경우 공간이 재활용되지 않음 (CUBRIDSUS-13355)

페이지 크기(기본 크기: 16K)에 근접한 크기의 레코드에 대해 INSERT/DELETE 작업이 반복되면 기존 여유 공간을 재활용하지 않고 새로운 페이지를 할당하는 오류를 수정했다.

한 테이블 내에서 총 20억건이 입력된 후, 새로운 입력 요청이 다량의 IO Read를 유발함 (CUBRIDSUS-12170)

해당 문제는 데이터의 입력과 삭제가 함께 수행되는 환경에서 발현되며, 삭제된 건수와 상관없이 DB생성 이후 총 입력된 건수가 20억건을 넘어서면 문제가 발생할 수 있다.

AUTO_INCREMENT 칼럼에 정의된 SERIAL의 CACHE 크기가 0보다 크면 서버 프로세스에서 메모리 누수가 발생함 (CUBRIDSUS-12628)

CREATE TABLE foo (a INT AUTO_INCREMENT, b DATETIME);
ALTER SERIAL foo_ai_a INCREMENT BY 1 CACHE 5000;

안정성

UNION ALL이 많은 질의 또는 표현식의 중첩이 많은 질의 수행 시 DB 서버가 비정상 종료함 (CUBRIDSUS-12208)

UNION ALL이 많은 질의 또는 표현식의 중첩이 많은 질의 수행 시 DB 서버가 비정상 종료했으나, 오류 처리하도록 수정했다.

MERGE 문의 INSERT 구문을 통해 DEFAULT 값이 입력되는 경우 DB서버 프로세스가 비정상 종료함 (CUBRIDSUS-12608)

CREATE TABLE foo(
    a INT PRIMARY KEY,
    b INT,
    c TIMESTAMP DEFAULT SYS_TIMESTAMP
);

MERGE INTO foo A
USING db_root ON (A.a = 1)
WHEN MATCHED THEN UPDATE SET A.b = A.b + 1
WHEN NOT MATCHED THEN INSERT (A.a, A.b) VALUES(1, 1);

GROUP BY 최적화(skip group by)가 적용되는 SELECT 질의문의 SELECT 리스트 중 오버플로우(overflow)된 칼럼이 존재하면 DB 서버가 비정상 종료함 (CUBRIDSUS-12464)

칼럼 값의 크기가 DB 볼륨 1 페이지(기본값 16KB)를 초과하는 오버플로우가 발생하면 DB 서버가 비정상 종료하는 현상을 수정했다.

CREATE TABLE FOO (id INT PRIMARY KEY, name STRING);
INSERT INTO foo SELECT ROWNUM, LPAD('A', 3*16*1024, 'A') FROM DB_CLASS;
UPDATE foo SET name='A' WHERE id % 2 = 1;
SELECT name, id FROM tbl GROUP BY id;

자동 커밋이 OFF인 상태에서 DEFERRED TRIGGER가 발동되는 UPDATE 문 수행 시 CSQL/CAS가 비정상 종료함 (CUBRIDSUS-12989)

자동 커밋이 OFF인 상태에서 아래 질의문들을 2회 반복 실행하면 수정 이전 버전에서는 CSQL/CAS가 비정상 종료한다.

DROP TABLE tb1;
CREATE TABLE tb1(id INT PRIMARY KEY,col INT);
INSERT INTO tb1 VALUES(1,60),(2,80),(3,70);

CREATE TRIGGER trg1
DEFERRED UPDATE ON tb1
if (obj.col > 100)
    EXECUTE UPDATE tb1 SET col=100 WHERE id=obj.id;

UPDATE tb1 SET col=120 WHERE id=2;
COMMIT;

INSERT ... ON DUPLICATE KEY UPDATE ... 문 수행 시 DB 서버가 비정상 종료할 수 있음 (CUBRIDSUS-12969)

CREATE TABLE tb1 (a INT UNIQUE);
INSERT INTO tb1 VALUES (1);
PREPARE S FROM 'INSERT INTO tb1 SET a = 1 ON DUPLICATE KEY UPDATE a = ?; ';
EXECUTE S USING '1';

자동 커밋 OFF 상태에서 테이블을 생성하고 지연 트리거를 추가한 후 테이블을 제거했다가, 다시 생성한 후 커밋하면 CSQL 또는 CAS가 비정상 종료함 (CUBRIDSUS-13447)

-- csql> ;autocommit off
CREATE TABLE tb1 (a INT PRIMARY KEY AUTO_INCREMENT, grade INT);
CREATE TRIGGER tgr1 DEFERRED INSERT ON tb1 IF(grade > 100) EXECUTE INSERT INTO tb1(grade) VALUES(obj.grade);
INSERT INTO tb1(grade) VALUES(120);
DROP tb1;
CREATE TABLE tb1 (a INT PRIMARY KEY AUTO_INCREMENT, grade INT DEFAULT 60);
INSERT INTO tb1(grade) VALUES(110);
-- csql> ;commit

DB 서버와 응용 프로그램의 연결을 중계하는 CAS가 다른 CAS로 변경된 이후 사용자의 요청을 처리하지 못함 (CUBRIDSUS-13390)

수정 이전 버전에서는 CAS가 변경된 이후 PREPARE와 EXECUTE를 제외한 나머지 요청들을 처리하지 못한다. 이 현상의 예로 JDBC 응용 프로그램에서 CUBRIDDatabaseMetaData.getTables()을 호출하면 통신 에러(communication error)가 발생한다.

브로커가 새로운 CAS를 생성하는데 계속 실패하면서 드라이버의 연결이 안 됨 (CUBRIDSUS-12567)

브로커가 새로운 CAS를 생성하는데 계속 실패하면서 드라이버의 연결이 안 되는 현상을 수정했다. 수정 이전 버전에서 드라이버에 login_timeout 속성이 명시되어 있으면 login timeout으로 실패하고 login_timeout 속성이 명시되지 않으면 무한 대기하는 상황이 발생한다.

브로커의 동작이 정지되면서 신규 연결 요청을 처리하지 못함 (CUBRIDSUS-12320)

응용 프로그램과 DB 사이의 연결을 유지하는 CAS 프로세스의 개수가 동적으로 자주 변경하는 환경에서 브로커의 동작이 정지되면서 신규 연결 요청을 처리하지 못하는 문제를 수정했다.

cub_master 프로세스가 비정상 종료함 (CUBRIDSUS-12196)

cub_master 프로세스의 에러 로깅으로 인해 cub_master 프로세스가 비정상 종료하는 현상을 수정했다.

SQL

SUM 함수의 입력 인자가 호스트 변수이고 이 값이 문자열이면 병합된 문자열을 출력함 (CUBRIDSUS-13131)

CREATE TABLE tbl(a int, b double, c char(10));
INSERT INTO tbl values(1,777,'cc');
INSERT INTO tbl values(2,3377,'cd');
INSERT INTO tbl values(3,3397,'cad');
INSERT INTO tbl values(3,3397,'cad');
INSERT INTO tbl values(5,37,'cd');

PREPARE stmt FROM 'SELECT SUM(?) FROM tbl GROUP BY c';
EXECUTE stmt USING '1';

9.2 버전까지는 병합된 문자열을 출력한다.

sum( ?:0 )
======================
'11'
'1'
'11'

9.3부터 숫자 변환이 가능하면 계산된 값을 출력하고, 숫자 변환이 불가능하면 오류를 출력한다.

sum( ?:0 )
======================
2.000000000000000e+00
1.000000000000000e+00
2.000000000000000e+00

TO_CHAR 함수에서 zerodate와 함께 리터럴 형식을 출력하도록 인자를 지정하는 경우 NULL을 반환하도록 수정 (CUBRIDSUS-11880)

zerodate에 대해 'Month', 'Day'와 같은 리터럴 형식을 지정하는 경우 NULL을 반환하도록 수정했다.

SELECT TO_ CHAR(timestamp '0000-00-00 00:00:00', 'Month Day YYYY')
NULL

참고로, 수정 이전 버전에서는 "Sunday Dec 0000"을 출력한다.

트리거 INSERT 문 내에서 LAST_INSERT_ID()가 사용되는 경우 잘못된 값이 입력됨 (CUBRIDSUS-12923)

트리거 INSERT 문 내에서 LAST_INSERT_ID()가 사용되는 경우 트리거를 발동한 INSERT의 LAST_INSERT_ID() 값이 아닌 바로 전에 수행한 INSERT 문의 LAST_INSERT_ID() 값이 적용되는 문제를 수정했다.

CREATE TABLE tbl1 (id INT AUTO_INCREMENT NOT NULL PRIMARY KEY);
CREATE TABLE tbl2 (id INT AUTO_INCREMENT(100,1), last_id INT);
CREATE TRIGGER t1 AFTER INSERT ON tbl1 EXECUTE INSERT INTO tbl2 VALUES(NULL, 1);
INSERT INTO tbl1 VALUES(NULL);

SELECT last_id FROM tbl2;

위의 SELECT 문을 수행할 때 칼럼 last_id의 값은 tbl1에 INSERT 시 적용된 LAST_INSERT_ID() 1이어야 하나, 수정 이전 버전에서는 NULL이 된다.

GROUP BY와 ORDER BY가 함께 존재하고 두 절의 칼럼이 다를때, 질의에 따라 잘못된 인덱스 스캔이 선택되어 질의 결과가 잘못 나옴 (CUBRIDSUS-12883)

CREATE TABLE foo (a INT, b INT, c INT);
CREATE INDEX idx_a ON foo (a);
INSERT INTO foo values (null, 1, 1);

SELECT b, c
FROM foo
WHERE a IS NULL GROUP BY b, c ORDER BY c, b;

수정 이전에는 위의 질의 수행 시 잘못된 인덱스 스캔이 선택되어 잘못된 결과를 출력하지만, 수정 이후에는 순차스캔으로 동작하여 정상 결과를 출력하게 된다. 하지만 순차 스캔으로 인해 성능이 저하될 수 있으므로, 해당 질의 계획을 확인하여 질의를 최적화하는 방안을 다시 고려해야 한다.

응용 프로그램 A가 prepare와 commit을 수행하고 응용 프로그램 B에 의해 테이블이 RENAME된 이후 A가 비정상 동작함 (CUBRIDSUS-12806)

client 1 client 2
pstmt = prepare("select * from foo")  
commit rename table foo as bar
pstmt.execute()  

수정 이전 버전에서 위의 "pstmt.execute()"를 수행하면 오류가 출력되어야 하나 정상 수행되는 문제를 수정했다.

동일한 조인 칼럼에 검색 조건이 2개 이상인 병합 조인(merge join) 수행 시 잘못된 결과를 출력함 (CUBRIDSUS-13199)

CREATE TABLE foo (i INT, j INT);
INSERT INTO foo VALUES (1, 1);
INSERT INTO foo VALUES (2, 1);

CREATE TABLE bar (v VARCHAR(10), i INT);
INSERT INTO bar VALUES ('one', 1);
INSERT INTO bar VALUES ('two', 2);

SELECT /*+ RECOMPILE USE_MERGE */
f.*, b.*
FROM foo f JOIN bar b ON f.i=b.i AND f.j=b.i;

위 질의를 수행하면 1건을 출력해야 하나 수정 이전에는 2건을 출력한다.

CONNECT BY 절을 사용하는 상관 부질의에서 오류가 발생함 (CUBRIDSUS-12485)

SELECT a.w_id wId , a.c_id cId ,
(
    SELECT SUBSTR(SYS_CONNECT_BY_PATH(name, ' > '), 4) fullname
    FROM innertbl
    WHERE cId = a.c_id /* workClsId */
    START WITH lvl = 1 CONNECT BY PRIOR WORK_CLS_ID = UPR_ID
) AS cname
FROM outertbl a
WHERE 1 = 1
and rownum < 10
ERROR: An I/O error occurred while reading page 1094004801 of volume "(null)".... Bad file description

INNER JOIN의 ON 절에 있는 조건이 ORDER BY에서 정렬에 사용될 경우 이 조건이 실행 계획에서 빠져서 잘못된 결과를 반환함 (CUBRIDSUS-12463)

SELECT /*+ ORDERED */ bb.*
FROM cc
INNER JOIN aa ON cc.a = aa.a AND cc.b=1
INNER JOIN bb ON bb.a = aa.a AND bb.a IN (1,2)
ORDER BY bb.b,bb.a;

AUTO_INCREMENT 칼럼을 가진 테이블의 이름을 변경한 이후 해당 칼럼에 INSERT하는 경우 고유 키 오류가 발생함 (CUBRIDSUS-6441)

CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (NULL);

-- rename AUTO_INCREMENT column
ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;

--continue to insert
 INSERT INTO t1 VALUES (NULL);
ERROR: Operation would have caused one or more unique constraint violations.

인덱스의 칼럼 개수가 9개 이상인 테이블의 카디널리티 출력 시 9번째 칼럼부터 항상 0으로 출력함 (CUBRIDSUS-12434)

인덱스의 칼럼 개수가 9개 이상인 테이블의 카디널리티 출력 시 9번째 칼럼부터 항상 0으로 출력하는 문제를 수정했다.

수정 이전에는 인덱스 칼럼 개수가 9개 이상이면 9번째 칼럼의 카디널리티 값부터 0이 되는 문제가 존재했다. 수정 이후에는 SHOW INDEX 문 수행 시 인덱스를 구성하는 전체 칼럼에 대한 카디널리티 정보를 출력하도록 변경했다.

SHOW INDEX 문 또는 INDEX_CARDINALITY 함수를 사용하여 카디널리티 값을 출력할 수 있다.

SHOW INDEX IN tbl;
SELECT INDEX_CARDINALITY('foo', 'idx1', 8);

"SELECT 'a' 'b'" 질의 수행 시 칼럼 이름이 잘못 출력됨 (CUBRIDSUS-12283)

"SELECT 'a' 'b'" 질의 수행 시 칼럼 이름으로 'ab'를 출력해야 하나, 'a'만 출력하는 현상을 수정했다.

SELECT 'a' 'b';

  'a'
======================
  'ab'

cubrid.conf의 plus_as_concat 파라미터의 값이 no일때 db_partition 카탈로그 테이블의 SELECT 질의를 수행하는데 실패함 (CUBRIDSUS-12557)

수정 이전 버전에서 다음과 같은 오류가 출력된다.

SELECT * FROM db_partition;
ERROR: before ' + [p].[pname] AS [partition_class_name], CASE WHEN [p].[ptyp...'
Cannot coerce '__p__' to type double.

오버플로우 키를 가진 고정 길이 CHAR 타입 칼럼에 데이터를 INSERT하지 못함 (CUBRIDSUS-11498)

키의 크기가 DB 볼륨의 1/4 페이지(페이지 크기 기본값 16KB)를 초과하여 오버플로우 키로 설정된 CHAR 타입 칼럼에 데이터를 INSERT할 때, 페이지 분할 중 B-tree의 구분자(separator)가 크게 생성되면 INSERT가 실패할 수 있는 현상을 수정했다.

LEFT OUTER JOIN과 INNER JOIN이 섞여 있는 경우 WHERE의 절의 조건이 정상적으로 적용되지 않음 (CUBRIDSUS-11312)

수정 이전 버전에서 아래와 같은 질의는 잘못된 결과를 출력한다.

SELECT /*+ RECOMPILE */ eee.nm, ddd.nm
FROM aaa
, bbb
LEFT OUTER JOIN ccc ON bbb.id = ccc.id
LEFT OUTER JOIN ddd ON bbb.key2 = ddd.key1
,eee
WHERE aaa.id = bbb.id
AND bbb.key1 = eee.key1
AND (ddd.nm = 'aaa' OR eee.nm = 'bbb')
AND aaa.id = 1;

집계 함수와 GROUP BY ... WITH ROLLUP 절을 포함하는 질의 수행 시 실패함 (CUBRIDSUS-11291)

CREATE TABLE tbl (a int, b int);
INSERT INTO tbl values (1, 1);
SELECT a, SUM(DISTINCT b)
FROM tbl GROUP BY a WITH ROLLUP;
ERROR: Unknown query identifier: 0.

DEFAULT 값이 ''인 칼럼에 대해 시스템 카탈로그에 NULL로 잘못 출력됨 (CUBRIDSUS-10946)

CREATE TABLE tbl (a VARCHAR DEFAULT '');

SELECT attr_name, default_value
FROM db_attribute
WHERE class_name = 'tbl';
  attr_name default_value
============================================
  'a' NULL

SELECT 리스트가 상수로 해석되는 뷰에 대해 SELECT 질의 수행 시 실패함 (CUBRIDSUS-12099)

CREATE TABLE t1 (i1 INT, s1 STRING);
CREATE VIEW v1 AS SELECT q.* FROM (SELECT CASE WHEN i1=1 THEN ABS('1') END FROM t1) Q;
SELECT * FROM v1;
ERROR: In line 1, column 66 before ' [ abs( cast('1' as double))] end from [t1] [t1]) [q] ([q_1])'
Syntax error: unexpected 'as', expecting END

시스템 테이블 혹은 시스템 뷰의 소유자 변경을 허용하지 않도록 수정 (CUBRIDSUS-10947)

CALL LOGIN('dba') ON CLASS db_user;
CREATE USER test_user;
ALTER VIEW db_class OWNER TO test_user;

수정 이후 위의 질의를 수행하면 아래 에러가 발생한다.

ERROR: To change the owner of a system class is not allowed.

질의 계획 캐시에 대한 희생자(victim) 선정 방식 및 희생자 개수 변경 (CUBRIDSUS-12920)

질의 계획 캐시가 가득 찰 때(full) 희생자를 선정하는 방식을 LRU 방식으로 변경하였다. 또한 캐시가 가득 찰 때 선택하는 희생자 개수도 기존에는 2% 정도를 선택하여 제거하는 방식이었으나, 한 개의 희생자만을 제거하는 방식으로 변경되었다.

따라서 수행되는 전체 질의의 개수가 cubrid.conf의 max_plan_cache_entries 개수를 넘는 환경에서는 질의 계획 캐시가 가득 차는 회수("cubrid plandump" 명령 출력 시 "FULL"의 값)가 기존보다 더 많아질 수 있다.

$ cubrid plandump tdb

CACHE        MAX        NUM     LOOKUP        HIT       MISS       FULL
entry         10          0         42          0         42         11
......

ORDER BY 절 또는 GROUP BY 절이 없이 DISTINCT.. LIMIT를 포함하는 질의를 수행하는 경우 결과 건수가 맞지 않음 (CUBRIDSUS-12950)

CREATE TABLE ddd (d INT);
INSERT INTO ddd VALUES (0), (0), (1), (1), (2), (2);

SELECT DISTINCT d FROM ddd LIMIT 2;

수정 이전 버전에서 위의 질의를 수행하면 2건이 아닌 1건을 출력하는 문제가 발생한다.

TRUNC 함수의 입력 인자 칼럼이 SELECT 리스트에 별도로 포함되는 경우 TRUNC 함수의 결과와 같은 값을 출력함 (CUBRIDSUS-13241)

CREATE TABLE tbl(a DATETIME);
INSERT INTO tbl VALUES('2012-05-05 10:10:10 AM');

SELECT a, TRUNC(a, 'day') FROM tbl;
a trunc(a,'day')
===============================================
10:10:10.000 AM 04/29/2012 04/29/2012

응용 프로그램에서 PREPARE->EXECUTE->테이블 재성성 이후 다시 EXECUTE를 수행하면서 바인딩되는 칼럼의 타입이 기존 테이블과 다르면 오류가 발생함 (CUBRIDSUS-12745)

CREATE TABLE tbl (i INT);

INSERT INTO tbl VALUES(?); -- prepare & execute

DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl (i STRING); -- the type of a column is changed

INSERT INTO tbl VALUES(?); -- execute with previous prepare statement

CREATE TABLE tbl (i int);
Semantic: Cannot coerce host var to type integer.

INNER JOIN과 LEFT OUTER JOIN이 같이 있는 질의를 수행하면 CAS가 비정상 종료함 (CUBRIDSUS-13207)

SELECT tbl3.code, tbl3.temp
FROM tbl1
INNER JOIN tbl2 ON tbl2.id = tbl1.id
LEFT JOIN tbl3 ON tbl3.code = tbl1.code and tbl3.name = 'AAA';

GROUP_CONCAT의 구분자, STR_TO_DATE의 날짜 형식 리터럴, 또는 LIKE ... ESCAPE 뒤의 이스케이프 리터럴을 포함하는 질의문으로 생성한 뷰를 가지고 질의를 수행하면 오류가 발생함 (CUBRIDSUS-13062)

CREATE TABLE tbl (a VARCHAR(10));
INSERT INTO tbl VALUES ('a'),('b'),('c');

CREATE VIEW vw AS
    SELECT GROUP_CONCAT(a ORDER BY a SEPARATOR ':') col
    FROM tbl;

SELECT * FROM vw;
ERROR: In line 1, column 45 before ' iso88591_bin) from [tbl] [tbl]'
Syntax error: unexpected 'collate', expecting ')'

수정 이전에는 위와 같은 질의문으로 뷰를 생성하면 리터럴 뒤에 "COLLATE iso88591_bin"과 같이 COLLATE 수정자가 자동으로 추가되는데, CUBRID는 이 구문을 허용하지 않기 때문에 이 뷰를 가지고 질의를 수행하면 오류가 발생한다.

COLLATE 설정을 허용하지 않는 예는 아래와 같이 GROUP_CONCAT의 구분자 리터럴, STR_TO_DATE의 날짜 형식 리터럴, 또는 LIKE ... ESCAPE 뒤의 이스케이프 리터럴에 COLLATE가 명시되는 경우이다.

SELECT GROUP_CONCAT(a ORDER BY a SEPARATOR ':' COLLATE iso88591) from tbl;
SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y' COLLATE iso88591);
SELECT * FROM tbl WHERE a LIKE 'a%' ESCAPE '@' COLLATE iso88591;

수정 이후에는 뷰를 생성할 때 위와 같은 리터럴 뒤에 COLLATE 수정자를 자동으로 추가하지 않는다.

ORDERBY_NUM() 조건에 부질의(subquery) 사용 시 CAS 프로세스가 비정상 종료함 (CUBRIDSUS-13036)

SELECT /*+ recompile */ *
FROM t1 a
WHERE a.b BETWEEN 1900 AND 2000
ORDER BY a.id
FOR ORDERBY_NUM() BETWEEN 1 AND (SELECT COUNT(*) FROM t1);

커버링 인덱스의 칼럼에 NULL 값이 존재할 때 커버링 인덱스 스캔으로 GROUP BY 절을 포함하는 질의를 수행하면 부정확한 결과를 출력함 (CUBRIDSUS-13006)

CREATE TABLE foo (id VARCHAR(60), stat VARCHAR(15));
INSERT INTO foo VALUES ('line', '1');
INSERT INTO foo VALUES ('line', '1');
INSERT INTO foo VALUES ('line', '1');
INSERT INTO foo VALUES ('line', null);
INSERT INTO foo VALUES ('line', null);

CREATE INDEX idx1 ON foo (id, stat);

SELECT /*+ RECOMPILE */ COUNT(*) cnt, id, stat
FROM foo
WHERE id > ''
GROUP BY id, stat
ORDER BY cnt desc;
  cnt id stat
======================================
    3 'line' '1'
    1 'line' NULL
    1 'line' NULL

수정 이전에는 위의 질의 수행 결과로 3건을 출력하나, 수정 이후 2건을 정상적으로 출력한다.

  cnt id stat
======================================
    3 'line' '1'
    2 'line' NULL

UNION 문 끝에 ORDER BY ... LIMIT 절이 존재하면 오류를 반환하도록 수정 (CUBRIDSUS-12982)

UNION 문 끝에 ORDER BY ... LIMIT 절이 존재하면 UNION 결과 전체에 반영해야 하는지 또는 부질의(subquery)에 적용해야 하는지 판단할 수 없으므로 오류를 반환하도록 수정했다.

높은 정밀도를 요구하는 FLOAT 타입 계산 시 잘못된 결과를 출력함 (CUBRIDSUS-12978)

CREATE TABLE foo (r float);
INSERT INTO foo VALUES ( 5 );
INSERT INTO foo VALUES ( 987654321.987654321 );
INSERT INTO foo VALUES ( -987654321.987654321 );
SELECT SUM(r) FROM foo;

위의 계산 결과로 수정 이전에는 0을 반환하지만 수정 이후 5를 반환한다.

역순 인덱스를 스캔할 때 출력되는 질의 계획에서 "sort:" 정보가 반대로 출력됨 (CUBRIDSUS-12973)

정렬되는 최종 결과에 맞게 출력하도록 수정했다. 수정된 버전에서는 역순 인덱스를 오름차순 정렬로 스캔하면 "sort:" 정보가 "desc"로 출력되며, 내림차순 정렬로 스캔하면 "sort:" 정보가 "asc"로 출력된다.

CREATE TABLE tbl ( a INT, b INT, c INT);
CREATE INDEX idx1 ON tbl(a ASC, b DESC, c ASC);
INSERT INTO tbl VALUES(1,100, 30);
INSERT INTO tbl VALUES(1, 200, 20);
INSERT INTO tbl VALUES(30, 300, 10);
INSERT INTO tbl VALUES(100, 0, 10);
INSERT INTO tbl VALUES(1, 200, 30);
INSERT INTO tbl VALUES(1, 200, 20);
INSERT INTO tbl VALUES(1, 0, 1);
UPDATE STATISTICS ON tbl;

-- csql> ;plan detail
SELECT /*+ USE_IDX */ a,b,c
FROM tbl
WHERE a = 1 AND b = 200 AND c > 1
ORDER BY b DESC, c DESC LIMIT 10;
Query plan:

iscan
    class: tbl node[0]
    index: idx1 term[0] AND term[1] AND term[2] (covers) (multi_range_opt) (desc_index)
    sort: 3 desc => "asc" on the previous version
    cost: 1 card 1

EXTRACT 함수에서 버퍼 오버런(buffer overrun)이 발생함 (CUBRIDSUS-13354)

CREATE TABLE tbl(s1 CHAR(20), s2 CHAR(30));
INSERT INTO tbl VALUES ('1990-10-10 10:11:12.', '456');
SELECT s1, EXTRACT (millisecond FROM s1) AS result
FROM tbl;

위의 SELECT 질의를 수행하면 result 값으로 수정 이전 버전에서는 456을 출력하나, 수정 이후 0을 출력한다.

  s1 result
===================================
  '1990-10-10 10:11:12.' 456

GROUP_CONCAT 함수에서 입력 인자의 타입과 구분자의 타입이 둘 다 BIT/VARBIT 타입이거나 둘 다 BIT/VARBIT 타입이 아닌 경우만 허용하도록 수정 (CUBRIDSUS-13553)

CREATE TABLE tbl (id INT, col1 INT);
INSERT INTO tbl VALUES(1, 60);
INSERT INTO tbl VALUES(1, 50);

--error should be displayed after running the below query
SELECT id, GROUP_CONCAT(DISTINCT col1 ORDER BY 1 SEPARATOR X'31')
FROM tbl
GROUP BY id;

위의 질의를 수행하면 수정 이전에는 결과 건수도 없고 에러도 없는 현상이 발생하며, 수정 이후에는 에러를 출력한다.

RAND(column)을 분할 키로 사용하는 테이블에 INSERT ... SELECT 문을 수행할 때 RAND(column) 값이 동일하게 되어 데이터가 각 분할 테이블에 나뉘지 않음 (CUBRIDSUS-13522)

CREATE TABLE range_part (id INT) PARTITION BY RANGE (RAND(id))
(
    PARTITION under_half VALUES LESS THAN (1073741823),
    PARTITION over_half VALUES LESS THAN (2147483647)
);
CREATE TABLE tbl (i INT);
INSERT INTO tbl values (1),(2);
INSERT INTO range_part
SELECT * FROM tbl;

위의 INSERT ... SELECT 문을 수행하면 수정 이전에는 RAND(1)의 결과를 분할 키로 유지한 채 나머지 레코드들을 하나의 분할 테이블에만 저장했으나, 수정 이후에는 RAND(1)과 RAND(2)를 각 레코드의 분할 키로 사용하면서 결과 레코드가 두 개의 분할 테이블에 나뉘어 저장된다.

수정 이전 버전에서 이 현상은 INSERT ... SELECT 문일 때만 발생하며 INSERT ... VALUES 문에서는 발생하지 않는다.

다중 칼럼 고유 인덱스를 가진 분할 테이블에서 REPLACE 문 또는 INSERT ... ON DUPLICATE KEY UPDATE 문을 수행하면 고유 키 오류가 발생함 (CUBRIDSUS-13502)

CREATE TABLE tbl(a INT, b CHAR(10), c SMALLINT, PRIMARY KEY(a, b))
PARTITION BY HASH(a) PARTITIONS 5;
INSERT INTO tbl(a, b, c) VALUES(1, 'd', 100);
--unique violation error occurs
REPLACE INTO t1 SET a=1, b='d', c=999;
--unique violation error occurs
INSERT INTO tbl(a, b, c) VALUES(1, 'd', 999) ON DUPLICATE KEY UPDATE c=1;
ERROR: Operation would have caused one or more unique constraint violations. INDEX pk_tbl_a_b(B+tree: 0|185|960) ON CLASS tbl__p__p1(CLASS_OID: 0|487|1). key: {1, 'd¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡'}(OID: 0|980|2).

상관 부질의(correlated subquery) 조건이 존재하는 계층 질의 수행 시 잘못된 결과를 출력함 (CUBRIDSUS-13491)

SELECT foo.* FROM foo
WHERE EXISTS (SELECT 1 from goo WHERE foo.id = goo.id)
START WITH foo.parent=-1
CONNECT BY PRIOR foo.id = foo.parent;

오버플로우(overflow)되는 레코드, 즉 DB 볼륨 한 페이지의 크기(기본 크기: 16K)보다 큰 레코드에 LOB 타입 칼럼이 포함되어 있는 경우 LOB 타입이 아닌 다른 칼럼을 UPDATE한 이후 LOB 타입 칼럼을 SELECT하면 오류가 발생함 (CUBRIDSUS-13478)

CREATE TABLE foo (a STRING, b BLOB);
INSERT INTO FOO VALUES (REPEAT('0123456789', 2000), BIT_TO_BLOB(X'abcdef1234567890987654321fedcba'));
SELECT BLOB_TO_BIT(b) FROM foo;
UPDATE foo SET a = REPEAT('abcdeabcde', 2000);
SELECT BLOB_TO_BIT(b) FROM foo;
ERROR: External file "/home/user1/CUBRID/databases/testdb/lob/ces_524/foo.00001396576111615326_9340" was not found.

다국어

영어와 한국어를 제외한 언어로 출력 메시지를 지정하는 경우 일부 메시지의 출력 오류로 인해 해당 메시지를 출력하는 프로세스가 비정상 종료함 (CUBRIDSUS-12596)

예를 들어 수정 이전 버전에서 CUBRID_MSG_LANG 환경 변수의 값을 "tr_TR"로 설정하고 cubrid.conf의 lock_timeout_in_secs 파라미터 값을 10으로 설정하면 "deprecated parameter"임을 알리는 메시지를 출력하면서 해당 현상이 발생한다.

사용자 정의 변수를 시스템 콜레이션과 다른 콜레이션으로 설정할 수 있게 수정 (CUBRIDSUS-12155)

시스템 콜레이션이 iso88591일 때 "SET @v1='a' COLLATE utf8_en_cs;"와 같이 사용자 정의 변수를 시스템 콜레이션과 다른 콜레이션으로 설정할 수 있게 수정했다.

사용자 정의 변수와(또는) 호스트 변수끼리 비교하는 경우 두 피연산자 중 하나만 바이너리 콜레이션이면 바이너리가 아닌 콜레이션으로 변환이 가능하도록 수정 (CUBRIDSUS-12155)

사용자 정의 변수와(또는) 호스트 변수는 콜레이션 변환도가 둘 다 11이지만 두 피연산자 중 하나가 바이너리 콜레이션(utf8_bin, iso88591_bin, euckr_bin)이면 바이너리가 아닌 콜레이션으로 변환이 가능하다.

SET NAMES utf8;
SET @v1='a';
PREPARE stmt FROM 'SELECT COERCIBILITY(?), COERCIBILITY(@v1), COLLATION(?), COLLATION(@v1), ? = @v1';
SET NAMES utf8 COLLATE utf8_en_ci;
EXECUTE stmt USING 'A', 'A', 'A';

수정 이후 위의 질의 수행이 가능하다.

"SET NAMES" 문으로 문자셋과 콜레이션을 변경했는데도 CSQL 세션 변수의 콜레이션 정보가 잘못 출력됨 (CUBRIDSUS-12214)

SET NAMES euckr;
SELECT 'a' INTO :v1;
SELECT COLLATION (:v1);
'euckr_bin'
SET NAMES utf8;
SELECT 'a' into :v2;

SELECT COLLATION (:v2);
'euckr_bin'

수정 이전 버전에서는 "SET NAMES" 문으로 문자셋과 콜레이션을 변경했음에도 불구하고 위와 같이 변경되지 않은 콜레이션 정보를 출력하며, 아래와 같이 "RECOMPILE" 힌트를 주어야만 변경된 콜레이션 정보를 정상적으로 출력한다.

SELECT /*+ RECOMPILE */ COLLATION (:v2);
'utf8_bin'

DB의 문자셋이 eucKR인 경우 인덱스가 생성된 문자 타입 칼럼에 INSERT 수행 도중 실패할 수 있음 (CUBRIDSUS-12211)

CREATE TABLE t (i CHAR(3000));
CREATE UNIQUE INDEX i_t ON t(i);
INSERT INTO t
SELECT ROWNUM FROM db_class a, db_class b, db_class c LIMIT 10000;

--execution failure occurs.
INSERT INTO t
SELECT ROWNUM FROM db_class a, db_class b, db_class c LIMIT 10000 ON DUPLICATE KEY UPDATE i = i+10000;

ERROR: Execute: Query execution failure #10676.

호스트 변수를 가진 표현식의 콜레이션 추정 오류 수정 (CUBRIDSUS-12129)

CREATE TABLE tbl(a STRING);
INSERT INTO tbl values ('A'), ('a'), (NULL);
PREPARE STMT FROM 'SELECT a FROM tbl WHERE a IN (SELECT ?)';
EXECUTE STMT USING 'A';

위와 같은 질의 수행 시 아래의 오류가 발생하는 현상을 수정했다.

ERROR: Cannot coerce value of domain "character varying" to domain "*variable*".

문자열을 입력 인자로 하는 함수에서 인자들의 콜레이션이 서로 다름에도 불구하고 오류를 출력하지 않는 문제(CUBRIDSUS-13638)

PREPARE st1 FROM 'SELECT POSITION(? in ?)';
SET NAMES euckr;
EXECUTE st1 USING _iso88591'A','abc';

위의 질의에서 POSITION 함수에 입력되는 인자의 콜레이션은 서로 다르므로 오류를 출력해야 한다.

수정 이후 다음 오류를 정상적으로 출력한다.

ERROR: Incompatible code sets. The code sets of the arguments are incompatible.

IN 절 내에 존재하는 호스트 변수에 콜레이션이 서로 다른 값을 명시했음에도 불구하고 오류를 출력하지 않음 (CUBRIDSUS-13651)

SET NAMES iso88591;
PREPARE st FROM 'SELECT * FROM db_root WHERE ? IN (?, ?)';

-- error does not occur in the previous version.
EXECUTE st USING 'b', _euckr'a', 'a';

SQL 함수 내 인자의 콜레이션이 서로 다름에도 불구하고 오류를 출력하지 않음 (CUBRIDSUS-13467)

SET NAMES utf8 COLLATE utf8_en_cs;
PREPARE st1 FROM 'SELECT REPLACE(?, ?, ?)';
PREPARE st2 FROM 'SELECT FIND_IN_SET(?, ?)';

--no error occurs in the previous version
EXECUTE st1 USING _euckr'a', 'a', 'b';
EXECUTE st2 USING _euckr'a', 'a';

콜레이션 변환도를 결정할 수 없는 경우 COERCIBILITY 함수가 -1을 반환하도록 수정 (CUBRIDSUS-13782)

호스트 변수만을 입력 인자로 갖는 표현식은 실행 단계 이전에 콜레이션 변환도(coercibility)를 결정할 수 없으므로, 해당 표현식에 대해 COERCIBILITY 함수를 수행하는 경우 -1을 반환하도록 수정했다.

SET NAMES utf8
PREPARE st FROM 'SELECT COLLATION(UPPER(?)) col1, COERCIBILITY(UPPER(?)) col2';
EXECUTE st USING 'a', 'a';
  col1                         col2
===================================
  'utf8_bin'                     -1

분할

응용 프로그램에서 같은 PreparedStatement 객체를 가지고 분할(partition) 테이블을 삭제한 후 재성성하면 실패함 (CUBRIDSUS-12037)

stmt1 = conn.prepareStatement("create table t1(id int, a varchar(2), b varchar(2)) partition by hash(id) PARTITIONS 10;");
stmt1.execute();
stmt2 = conn.prepareStatement("drop table t1");
stmt2.execute();
stmt2.close();
stmt1.execute(); // error occurred here.

위의 예와 같이 실행하면 아래의 에러가 발생하면서 실패하는 현상을 수정했다.

System error (generate attr) in ../../src/parser/xasl_generation.c

분할 해시 테이블을 조인하는 경우 잘못된 결과를 출력함 (CUBRIDSUS-13079)

CREATE TABLE hash_test(id INT, parentid INT, text VARCHAR(32))
    PARTITION BY hash(id) PARTITIONS 4;
INSERT INTO hash_test VALUES (369, 71, 'AAAD'),(1048, 369, 'AAADC'),(71,11,'AAA');
SELECT *
FROM hash_test t1 inner join hash_test t2 on t1.id=t2.parentid inner join hash_test t3 on t2.id=t3.parentid where t3.id=1048;

위의 SELECT 질의를 수행하면 1개의 행을 출력해야 하지만, 수정 이전 버전에서는 같은 값을 가진 2개의 행을 출력한다.

       id parentid text id parentid text id parentid text
===========================================================
       71 11 'AAA' 369 71 'AAAD' 1048 369 'AAADC'
       71 11 'AAA' 369 71 'AAAD' 1048 369 'AAADC'

분할 테이블의 마지막 남은 하나의 분할을 ALTER 문으로 삭제하는 경우 출력하는 오류 메시지 수정 (CUBRIDSUS-13038)

CREATE TABLE tbl (
    id VARCHAR(50) NOT NULL,
    memo VARCHAR(20) NOT NULL,
    ymd int NOT NULL)
PARTITION BY RANGE ( ymd )
(PARTITION "200912_2" VALUES LESS THAN (20100101) ) ;

ALTER table ps drop partition "200912_2";

수정 이전에 출력하는 아래의 오류 메시지로는 원인을 파악하기 힘들다.

ERROR: before ' ; '
Invalid partition size.

수정 이후 보다 직관적인 아래의 오류 메시지를 출력한다.

Cannot remove all partitions, use DROP TABLE instead

함수 기반 인덱스를 가진 분할 테이블에 질의 수행 시 부정확한 결과를 출력함 (CUBRIDSUS-13003)

CREATE TABLE tbl(id INT, col VARCHAR(10))
    PARTITION BY RANGE(id)(
        PARTITION p1 VALUES LESS THAN (10),
        PARTITION p2 VALUES LESS THAN (100)
    );
INSERT INTO tbl values(1,'a');
INSERT INTO tbl values(21,'a');
CREATE INDEX idx ON tbl(MOD(id,2));
SELECT * FROM tbl WHERE MOD(id,2)=1;

분할을 재구성할 때 분할 이름이 같은 경우에도 오류를 출력하지 않음 (CUBRIDSUS-12965)

CREATE TABLE tbl(id INT, col CHAR(10))
    PARTITION BY RANGE(id)(
        PARTITION p1 VALUES LESS THAN (501),
        PARTITION p2 VALUES LESS THAN (1001)
    );

ALTER TABLE tbl REORGANIZE PARTITION p1 INTO (
    PARTITION p1 VALUES LESS THAN (200),
    PARTITION p1 VALUES LESS THAN (501)
);

수정 이전 버전에서 위의 ALTER 문을 수행하면 오류를 출력하지 않는다.

분할 테이블에서 분할 부분의 고유 키 칼럼에 대한 최대/최소값을 잘못 출력함 (CUBRIDSUS-13161)

CREATE TABLE tbl (id VARCHAR (40), col int)
PARTITION BY LIST (id) (
    PARTITION p1 VALUES IN ('Swimming', 'Athletics'),
    PARTITION p2 VALUES IN ('Judo', 'Taekwondo', 'Boxing'),
    PARTITION p3 VALUES IN ('Football', 'Basketball', 'Baseball')
);
INSERT INTO tbl VALUES('Swimming',1);
insert into tbl values('Boxing',2);
insert into tbl values('Football',3);
select min(col) from tbl__p__p2;

위의 질의 수행 결과는 수정 이전과 이후 모두 동일하게 2를 정상 출력한다. 그러나 아래의 질의 수행 결과는 수정 이전에는 잘못된 결과인 1을 출력한다.

CREATE UNIQUE INDEX idx ON tbl(col);
SELECT MIN(col) FROM tbl__p__p2;

분할 테이블에서 잘못된 인덱스 카디널리티(cardinality) 값을 출력함 (CUBRIDSUS-12577)

분할 테이블에 대해 "SHOW INDEX IN tbl"을 수행하면 잘못된 인덱스 카디널리티 값을 출력하는 오류를 수정했다.

HA

슬레이브 또는 레플리카 노드에서 serial.next_value 호출 시 잘못된 에러 메시지를 출력함 (CUBRIDSUS-12333)

ERROR: Execute: Internal I/O error for serial

수정 이후 아래의 메시지를 출력한다.

Attempted to update the database when updates are disabled.

copylogdb가 요청한 로그 페이지가 없는 경우 copylogdb 에러 로그에 에러 메시지를 기록하도록 수정 (CUBRIDSUS-12249)

HA 환경에서 copylogdb가 요청한 로그 페이지가 없는 경우 copylogdb와 서버의 에러 로그에 다음 메시지를 기록하도록 수정했다.

log writer: failed to get log page(s) starting from page id 108.

슬레이브 노드 또는 레플리카 노드에서 CSQL에 --sysadm 옵션만 사용하는 경우 DDL, INSERT 질의가 성공하지 못하도록 수정 (CUBRIDSUS-12187)

수정 이후 슬레이브 노드 또는 레플리카 노드에서 DDL, INSERT를 포함한 쓰기 질의가 성공하려면 --sysadm과 함께 --write-on-standby 옵션을 사용해야 한다.

정상적인 상황에서 HA 절체(failover) 수행 시 소요 시간을 줄이도록 개선 (CUBRIDSUS-12758)

복제 지연이 없고 모든 노드가 정상적인 상황에서 "cubrid heartbeat stop" 명령에 의해 HA 절체(failover)를 수행할 때 소요 시간이 이전 버전 대비 십여 초가 감소되었다.

슬레이브 노드의 DB 볼륨이 마스터 노드의 DB 볼륨보다 커짐 (CUBRIDSUS-12209)

슬레이브 노드의 DB 볼륨이 마스터 노드의 DB 볼륨보다 커지는 현상을 줄이기 위해, 슬레이브 노드의 복제 반영 주기(커밋 주기)가 자동으로 조절되도록 수정했다. 복제 로그를 슬레이브 노드의 DB에 반영하는 applylogdb 프로세스는 일정 시간 단위로 복제 로그에 대한 커밋을 수행하는데, 주기가 짧을수록 볼륨 재사용률이 높아져서 볼륨 크기가 불필요하게 증가하지 않게 된다. 반면, 주기가 짧아지면 복제 반영 속도가 늦어져서 복제 지연의 가능성이 높아진다. 수정 이전 버전에서는 복제 반영 주기가 고정되었으나, 수정 이후 버전에서는 복제 지연 정도를 계산하여 복제 반영 주기를 자동으로 조정한다.

마스터 노드와 슬레이브 노드 간 방화벽이 설정되어 있는 경우 장시간 동안 트랜잭션 로그가 복사되지 않으면 DB 서버 쪽 연결이 종료됨 (CUBRIDSUS-12194)

TCP 네트워크 프로토콜에 SO_KEEPALIVE 옵션을 적용하여, 위 제목의 현상으로 인해 마스터 DB에서 장애 발생 시 HA 절체(failover)가 정상 동작하지 않을 수 있는 문제를 수정했다.

또한, cubrid.conf에 tcp_keepalive 파라미터(기본값: yes)를 추가하여 TCP 네트워크 프로토콜에 SO_KEEPALIVE 옵션을 적용할지 여부를 지정할 수 있도록 수정했다.

HA 구동 시 장애 복구가 불가능한 경우를 판단하여 구동에 실패하도록 수정 (CUBRIDSUS-12459)

수정 이전 버전에서는 "cubrid heartbeat start" 명령으로 HA 구동 시 장애 복구가 불가능한 경우임에도 불구하고 성공 메시지를 출력하므로 HA 구동이 성공한 것으로 오인할 수 있다.

복제 재구축 스크립트에서 CUBRID_CHARSET 검사 부분 제거 (CUBRIDSUS-12430)

CUBRID_CHARSET 환경 변수는 9.2부터 더 이상 사용하지 않으므로 이 변수에 대한 검사는 불필요하게 되었다.

마스터와 슬레이브 사이에 VIEW 스키마에 대한 콜레이션이 불일치함 (CUBRIDSUS-12300)

CREATE TABLE t1 (id VARCHAR(100) COLLATE utf8_en_ci PRIMARY KEY);
INSERT INTO t1 VALUES ('a');

SET NAMES utf8 COLLATE utf8_en_cs;
CREATE VIEW v1 AS SELECT id='A' result FROM t1;
SELECT * FROM v1;

위에서 생성한 VIEW 스키마에 대해 수정 이전 버전의 마스터 노드에서는 아래와 같이 출력된다.

csql> ;sc v1

<Query_specifications>
 select [t1].[id]=_utf8'A' collate utf8_en_ci from [t1] [t1]

위에서 생성한 VIEW 스키마에 대해 수정 이전 버전의 슬레이브 노드에서는 아래와 같이 출력된다.

<Query_specifications>
 select cast([t1].[id] as varchar(100) collate utf8_en_cs)=_utf8'A' collate utf8_en_cs from [t1] [t1]

마스터 노드의 DB 서버 프로세스가 1분 이내에 재시작에 실패하는 경우 슬레이브로 역할을 변경하도록 수정 (CUBRIDSUS-12244)

수정 이전 버전에서는 같은 조건 하에서 마스터 노드가 동작을 정지하고 HA 절체(failover)가 발생한다.

서버 프로세스가 비정상 종료된 이후 재시작될 때, 명시한 시간 내에 서버 프로세스가 재시작되면 해당 노드를 HA 구성에서 제외(demote)하도록 수정 (CUBRIDSUS-7202)

HA 환경에서 서버 프로세스의 비정상 상황이 지속되는 경우 재시작의 무한 반복이 발생할 수 있고, 이런 경우를 유발하는 노드는 HA 구성에서 제외하는 것이 바람직하다. 따라서 수정 이후 버전에서는 ha_unacceptable_proc_restart_timediff 파라미터(기본값: 2분)를 제공하여 서버 프로세스의 비정상 종료 이후 명시한 시간 간격 이내에 재시작되면 비정상으로 간주하고, 해당 노드를 HA 구성에서 제외(demote)한다.

브로커와 DB 서버를 연결할 때 1차 연결에서 cubrid_broker.conf의 PREFERRED_HOSTS에 명시된 모든 호스트와 databases.txt의 db-host에 명시된 모든 호스트에 접속이 불가능하면 2차 연결 시 PREFERRED_HOSTS부터 다시 시도하도록 수정 (CUBRIDSUS-12353)

1차 연결 시에는 DB의 상태(active 또는 standby)와 복제 지연 여부를 확인하여, 이 두 가지 조건이 만족하는 경우에만 연결 여부를 결정한다. 2차 연결 시에는 이 두 가지 조건을 무시하고 네트워크 접속이 가능하면 연결을 성공시킨다. 단, "ACCESS_MODE=SO"인 경우에는 DB의 상태가 반드시 standby여야 한다.

수정 이전 버전에서는 1차 연결에서 PREFERRED_HOSTS와 db-host에 최초에 접속이 안 되면 2차 연결 시에는 PREFERRED_HOSTS의 호스트 접속을 시도하지 않고 db-host에 명시된 호스트에만 접속을 시도한다.

copylogdb 프로세스가 이미 삭제된 오래된 보관 로그를 요청할 때 DB 서버 프로세스가 비정상 종료됨 (CUBRIDSUS-12455)

시스템 파라미터 force_remove_archives의 값이 yes로 설정된 경우, copylogdb가 복사하지 않은 트랜잭션 로그를 DB 서버 프로세스가 지우는 것은 정상 동작이다. 그러나, 이후 copylogdb가 이 트랜잭션 로그를 요청할 때 서버 프로세스가 비정상 종료되는 문제를 수정하였다. 수정 이전과 이후의 버전에서 copylogdb가 복사하지 않은 트랜잭션 로그를 DB 서버 프로세스가 지우면 copylogdb 로그 파일에는 다음과 같은 에러 메시지가 기록된다.

Unable to mount disk volume "/home1/user1/CUBRID/log/message02_lgar39100".... No such file or directory
...
Internal error: unable to find log page 2327082503 in log archives.

"cubrid heartbeat start" 또는 "cubrid heartbeat reload" 명령 수행 시 cubrid_ha.conf의 ha_ping_hosts에 설정한 호스트들이 모두 핑 체크(ping check)에 실패함에도 불구하고 에러 메시지를 남기고 정상 수행됨 (CUBRIDSUS-12720)

수정 이후 버전에서 ha_ping_hosts에 설정한 모든 호스트가 핑 체크에 실패하는 경우 에러를 출력하며 명령 수행을 중단한다. 또한, 수정 이후 버전에는 1시간 주기로 ha_ping_hosts에 명시된 호스트를 점검하여 모든 호스트가 문제 있을 경우 일시적으로 ping check을 중지하고 5분 단위로 해당 호스트들이 정상화되었는지 검사하는 기능이 추가되었다.

copylogdb 프로세스의 응답이 늦어지면 상대방 노드의 DB 서버 프로세스가 비정상 종료할 수 있음 (CUBRIDSUS-12884)

copylogdb 프로세스가 존재하는 장비에 작업 부하가 커지면서 copylogdb 프로세스의 응답이 늦어지면 상대방 노드의 DB 서버 프로세스가 비정상 종료할 수 있는 현상을 수정했다.

레플리카 존재 시 split-brain 방지 기능이 동작하지 않음 (CUBRIDSUS-12986)

마스터 노드에서 슬레이브로 역할 변경(demote)이 필요한 경우 마스터 노드의 고립 여부에 따라 역할 변경 수행 여부를 결정하나, 수정 이전 버전에서는 레플리카가 존재하는 경우 마스터 노드는 고립이 아니라고 판단하여 역할 변경이 되지 않거나 혹은 불필요한 역할 변경이 발생한다.

브로커 다중화에서 모든 브로커 호스트가 장애로 판단되는 경우 재접속하는 방법 개선 (CUBRIDSUS-12977)

수정 이전 버전에서는 모든 호스트가 장애로 판단(unreachable)되면 2차 연결 이후에도 모든 호스트를 장애 노드로 판단하나 수정 이후 버전에서는 2차 연결 시 성공한 노드는 장애 노드 리스트에서 제외한다.

copylogdb 프로세스가 요청한 로그 파일을 서버로부터 받지 못할 경우 에러 메시지가 무한 반복됨 (CUBRIDSUS-13147)

수정 이전에는 다음의 에러 메시지가 콘솔에 무한 반복하여 출력된다.

Unable to mount disk volume "/home/cubrid/CUBRID/databases/xdb/xdb_lgar075".... No such file or directory

수정 이후, 문제가 발생한 노드는 아래와 같이 에러 로그를 남기고 copylogdb는 종료되어 재시작되지 않는다.

Process event: Encountered an unrecoverable error and will shut itself down.

CAS가 특정 상황에서 일정 시간 경과 시 서버에 재연결을 시도하도록 수정 (CUBRIDSUS-12140)

CAS가 다음의 상황에서 일정 시간 경과 시 서버에 재연결을 시도하도록 수정했다.

  • PREFERRED_HOSTS가 아닌 다른 호스트에 연결한 경우
  • RO 브로커인데 active 서버에 연결한 경우

일정 시간은 RECONNECT_TIME(기본값: 600s) 브로커 파라미터로 명시하며, 이 값이 0이면 재연결을 시도하지 않는다.

Sharding

SHARD 힌트로 인해 broker_log_top 수행 결과에서 동일한 질의가 구분되어 집계됨 (CUBRIDSUS-12410)

해당 현상이 발생하지 않도록 하기 위해, broker_log_top 수행 시 질의 힌트를 제거한 이후에 질의 개수를 집계하도록 수정했다.

질의 에러 발생 시 발생한 SHARD/CAS 위치를 알 수 있도록 에러 메시지 개선 (CUBRIDSUS-12115)

Sharding 환경에서 질의 에러 발생 시 어느 SHARD/CAS에서 발생했는지 알 수 있도록 에러 메시지를 개선했다.

CAS 에러 메시지의 가장 마지막에는 아래 형식의 SHARD/CAS 정보가 출력된다.

[SHARD/CAS ID %d,%d]

드라이버 에러 메시지에는 기존의 CAS 정보 대신 PROXY 정보를 출력한다.

// 수정 이전

[CAS INFO %s],[SESSION - %d],[URL - %s]

// 수정 이후
[PROXY INFO %s],[URL - %s]

SHARD 환경에서 CAS가 드라이버의 접속 정보를 이용하여 DB에 접속하도록 수정 (CUBRIDSUS-12073)

SHARD_DB_USER/SHARD_DB_PASSWORD 파라미터는 제거될 예정(deprecated)이므로, 수정 이후 버전에서는 응용 프로그램에서 제공하는 DB 접속 방법을 사용할 것을 권장한다.

SHARD 환경에서 특정 시간 동안 아무런 요청이 없으면 CAS가 DB와의 접속을 끊도록 수정 (CUBRIDSUS-12073)

SHARD_PROXY_CONN_WAIT_TIMEOUT(기본값: 8시간) 브로커 파라미터를 추가하여, 이 파라미터로 명시한 시간 동안 아무런 요청이 없으면 CAS가 DB와의 접속을 끊도록 수정했다. 이 기능은 이전 비밀번호 정보를 지닌 CAS가 계속 유지되는 것을 방지한다.

SHARD 환경에서 한 응용 프로그램이 동일한 SQL 문에 대해 동시에 여러 개를 PREPARE한 후 실행하면 질의 결과가 잘못됨 (CUBRIDSUS-11977)

PreparedStatement pstmt1 = con.prepareStatement(sql);
PreparedStatement pstmt2 = con.prepareStatement(sql);

pstmt1.setInt(1, 2);
ResultSet rs1 = pstmt1.executeQuery();
pstmt2.setInt(1, 4);
ResultSet rs2 = pstmt2.executeQuery();

// 수정 이전 버전에서 아래를 실행하면 rs2의 결과가 섞여서 출력되는 오류가 존재한다.
while (rs1.next()) {
  System.out.println(rs1.getInt(1) + " : " + rs1.getInt(2));
}

SHARD 환경에서 SQL 주석 뒤에 개행 문자가 없으면 에러가 발생함 (CUBRIDSUS-12321)

SHARD 환경에서 SQL 주석 뒤에 "\n"이 없으면 에러가 발생하는 현상을 수정했다.

select 1; --this is comment

드라이버

[JDBC][CCI] CAS의 keepalive 패킷 전송 주기가 OS 설정을 따라가도록 수정하고, 드라이버의 소켓도 keepalive 시간을 사용하도록 수정 (CUBRIDSUS-12354)

CAS에서 사용하는 소켓의 keepalive 패킷전송 주기가 OS 설정을 따라가도록 수정했고, JDBC와 CCI드라이버의 소켓도 CAS 소켓과 동일하게 keepalive 시간을 사용하도록 수정했다. 이 수정으로 인해 드라이버와 CAS 간 방화벽에 의해 연결이 끊기는 현상이 줄어들게 되었다.

[JDBC][CCI] 2008 R4.x 드라이버로 9.x 이상 버전에 접속할 때 DATASOURCE를 사용하면 DB 서버가 비정상 종료함 (CUBRIDSUS-12450)

2008 R4.x 드라이버로 9.x 이상 버전에 접속할 때 CCI의 DATASOURCE 또는 JDBC의 XADataSource를 사용하면 DB 서버가 비정상 종료하는 현상을 수정했다.

[JDBC][CCI] 연결 URL 문자열에 로깅 관련 속성 중 하나라도 포함되면 로깅 디렉터리가 생성되어 있지 않은 경우 생성되도록 수정 (CUBRIDSUS-11320)

CCI 인터페이스의 로깅 관련 속성(property)에는 logBaseDir, logFile, logSlowQueries, logTraceApi, logTraceNetwork가 있다. JDBC 인터페이스의 로깅 관련 속성(property)에는 logFile, logOnException, logSlowQueries가 있다.

[JDBC] 다중 행 INSERT 수행 이후 Statement.getGeneratedKeys 메서드 호출 시 오류가 발생함 (CUBRIDSUS-13116)

stmt.execute("INSERT INTO t1(b) values(1), (2), (3);",Statement.RETURN_GENERATED_KEYS);

rs=stmt.getGeneratedKeys();
System.out.println(rs.getInt(1));
Exception in thread "main" java.lang.NullPointerException
    at cubrid.jdbc.driver.CUBRIDResultSet.checkRowIsValidForGet(CUBRIDResultSet.java:1710)

[JDBC] DatabaseMetaData 객체의 일부 메소드에서 실제와 다른 값을 반환함 (CUBRIDSUS-10806)

getResultSetHoldability(), getMaxBinaryLiteralLength(), getMaxCharLiteralLength(), getMaxUserNameLength() 메소드가 정상적인 값을 반환하도록 수정했다.

[JDBC] ResultSetMetaData.isAutoIncrement()를 호출하면 NullPointerException 발생 (CUBRIDSUS-12612)

DatabaseMetaData를 통해 생성된 ResultSet에서 (예, DatabaseMetaData.getTables()) ResultSetMetaData를 사용할 때 isAutoIncrement()를 호출하면 NullPointerException이 발생하는 오류를 수정했다.

DatabaseMetaData m = c.getMetaData();
ResultSet r = m.getTables(null, null, "foo", null);
ResultSetMetaData rm = r.getMetaData();

for (int i = 0; i < rm.getColumnCount(); i++) {
    System.out.println(String.format("[%s][%s]", rm.getColumnName(i + 1), rm.isAutoIncrement(i + 1) ? "true" : "false"));
}

[JDBC] Datasource을 이용한 접속 시 연결 URL 문자열을 사용할 수 있도록 수정 (CUBRIDSUS-12429)

CUBRIDDataSource 클래스에 setUrl 메서드를 추가하여, 연결 URL 문자열을 사용할 수 있도록 수정했다. 연결 URL 문자열에는 IP, 포트, DB 이름 뿐만 아니라 charset, logSlowQueries 등과 같이 CUBRID에서 정의한 속성(property)들을 포함할 수 있다.

import cubrid.jdbc.driver.CUBRIDDataSource;
...

ds = new CUBRIDDataSource();
ds.setUrl("jdbc:cubrid:10.113.153.144:55300:demodb:::?charset=utf8&logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true");

[JDBC] getObject()를 통해 Timestamp 타입 또는 Date 타입으로 저장된 데이터를 가져올 때 "NULL pointer exception" 에러가 발생함 (CUBRIDSUS-12686)

한 예로, 수정 이전 버전에서 iBatis를 사용하여 Timestamp 또는 Date 타입 값을 가져올 때 에러가 발생한다.

[JDBC] 다중 SQL 문에서 "SELECT ... ; UPDATE ... ; SELECT ... " 순서로 있을 때 UPDATE 문 이후 SELECT 문을 수행했음에도 불구하고 PreparedStatement.getUpdateCount() 메서드가 -1을 출력하지 않음 (CUBRIDSUS-10253)

SELECT 문에서 PreparedStatement.getUpdateCount() 메서드는 -1을 출력해야 한다. 그러나 UPDATE 문 수행 이후 다시 SELECT 문을 호출하면 앞에 수행한 UPDATE 문에 의해 저장된 PreparedStatement.getUpdateCount()의 값이 그대로 유지되는 문제를 수정했다.

String sql = "SELECT * FROM table1;" +
    " UPDATE table1 SET col1 = 1;" +
    " SELECT * FROM table1;" +
    " SELECT * FROM table2;" +
    " SELECT * FROM table3;";

preStmt = conn.prepareStatement(sql);
rs = preStmt.getResultSet();
preStmt.execute();

int updateCount = preStmt.getUpdateCount();
System.out.println("updateCount = " + updateCount);

if (updateCount == -1) {
    printdata(rs);
}

while(preStmt.getMoreResults() || preStmt.getUpdateCount() != -1)
{
    rs = preStmt.getResultSet();
    updateCount = preStmt.getUpdateCount();
    System.out.println("updateCount = " + updateCount);

    if (updateCount == -1) {
        printdata(rs);
    }
}

[JDBC] 연결 URL이 잘못된 호스트 또는 포트 등으로 유효하지 않은 경우 예외가 발생하도록 변경 (CUBRIDSUS-13230)

수정 이전 버전에서는 연결 메서드가 NULL을 반환하지만 예외(exception)가 발생하지는 않는다.

[CCI] 함수의 입력 인자에 NULL 값이 입력되는 경우를 검사하도록 수정 (CUBRIDSUS-12817)

수정 이전 버전에서 포인터 입력 인자에 NULL 값이 입력되면 응용 프로그램이 비정상 종료될 수 있다.

[CCI] datasource에서 연결 개수의 제한을 동적으로 변경할 수 있도록 수정 (CUBRIDSUS-12616)

datasource에서 연결 개수를 제한하는 pool_size 속성을 변경 가능하도록 하고, datasource 생성 시 연결 풀에 유지되는 최대 연결 개수를 지정하는 max_pool_size 속성을 추가했다. 수정 이후 pool_size 속성은 cci_datasource_chagne_property 함수를 통해 최대 max_pool_size 값까지 변경될 수 있다.

[CCI] prepare 또는 execute 함수에서 내부적인 재접속 시 login_timeout 속성이 적용되도록 수정 (CUBRIDSUS-12530)

수정 이전 버전에서는 prepare 또는 execute 함수에서 내부적인 재접속 시 로그인 타임아웃이 적용되지 않았으나 login_timeout이 설정되어 있을 경우 반영되도록 수정했다.

[CCI] cci_datasource_destroy 함수의 오류로 인해 닫아야 할 DB 연결을 재사용할 수 있는 문제 (CUBRIDSUS-12471)

어떤 스레드의 cci_datasource_destroy 함수에서 DB와의 연결을 모두 닫는 과정에서 다른 스레드의 cci_datasource_borrow 함수가 수행되는 경우 닫아야 할 연결을 재사용할 수 있는 문제를 수정했다.

[CCI] cci_prepare_and_execute 함수에서 에러 발생 시 exec_retval 인자의 출력 값이 해당 함수의 에러 반환 값과 일치하도록 수정 (CUBRIDSUS-11828)

cci_prepare_and_execute 함수 수행 중 에러 발생 시 질의에 영향을 받는 행(affected rows)의 개수를 출력하는 exec_retval 인자의 출력 값이 해당 함수의 에러 반환 값과 항상 같도록 수정했다.

수정 이전에는 내부적인 재연결로 인한 에러 발생 시 함수의 반환 값과 exec_retval의 출력 값이 다르다.

[CCI] cci_prepare 함수의 prepare flag 로 CCI_PREPARE_INCLUDE_OID를 지정하고 SELECT ... UNION 문을 수행하면 비정상적으로 동작함 (CUBRIDSUS-11171)

수정 이전 버전에서 cci_execute 함수 수행 시 OS가 Windows이면 응용 프로그램이 비정상 종료되며, Linux이면 함수 수행에 실패한다.

[CCI] cci_datasource_change_property 함수에서 변경하고자 하는 pool_size 의 값이 max_pool_size 값보다 클 경우 출력되는 에러 메시지가 부적절함 (CUBRIDSUS-13011)

수정 이전에는 다음 에러 메시지를 출력한다.

Invalid property type

수정 이후 다음 에러 메시지를 출력한다.

Invalid property value

[CCI] cci_bind_param 함수에서 STRING 타입을 DATETIME 타입으로 변환하면 입력값과 달라짐 (CUBRIDSUS-13581)

snprintf (sql, 4096, "insert into foo values(?,?)");
req1 = cci_prepare (con, sql, 0, &err);
res = cci_bind_param(req1, 2, CCI_A_TYPE_STR, "2012/01/01 01:03:05.0", CCI_U_TYPE_DATETIME, 0);

수정 이전 버전에서는 변환된 데이터의 초가 입력 데이터와 다르게 변환된다.

2012/1/1 1:3:3.000

[CCI] cci_datasource_release 함수의 실행이 성공할 때 0을 반환함 (CUBRIDSUS-13576)

이 함수의 실행이 성공하면 1을 반환하도록 수정했다.

유틸리티

마지막 DB 볼륨 파일이 삭제되었음에도 불구하고 DB 구동 시 성공함 (CUBRIDSUS-13279)

마지막 DB 볼륨이 삭제되면 DB 구동 시 실패하도록 수정했다.

"cubrid broker status -f" 명령 수행 결과에 이전에 접속한 호스트 이름이 출력됨 (CUBRIDSUS-12573)

databases.txt의 db-hosts에 다수의 호스트가 설정된 상태에서 절체 등으로 인해 CAS가 다른 호스트에 재연결되는 경우 "cubrid broker status -f" 명령을 수행하면 재연결된 호스트 정보가 아닌 이전의 호스트 정보가 출력되는 문제를 수정했다.

"cubrid broker reset"이 동작하지 않음 (CUBRIDSUS-12106)

다수의 standby HA 서버 구성 (host1:host2)에서 host1의 서버 이상으로 RO/SO 브로커가 host2에 연결된 경우 host1이 서버 복구 후 "cubrid broker reset" 명령을 수행해도 host1에 재연결되지 않고 host2에 연결이 유지되는 현상을 수정했다.

백업 수행 시 -B 혹은 -D 옵션으로 주어진 경로에 접근 권한이 없거나 디스크 여유 공간이 없으면 동작을 멈춤(hang) (CUBRIDSUS-12286)

수정 이전 버전에서 위의 현상이 발생하면 체크포인트가 실행되지 않아서 보관 로그 파일이 삭제되지 않을 수 있다.

"cubrid optimizedb"를 수행하면 샘플링 방식으로 통계 정보를 갱신하도록 수정 (CUBRIDSUS-12087)

수정 이전에는 전체 데이터를 스캔(full scan)하여 통계 정보를 갱신했으므로 실행에 많은 시간이 요구되었다.

"cubrid diagdb" 수행 시 인덱스 이름을 포함하도록 수정 (CUBRIDSUS-11472)

-d 2(파일 용량 정보 출력), -d 3(힙 용량 정보 출력) 또는 -d 4(인덱스 용량 정보 출력) 옵션으로 해당 정보를 출력할 때 인덱스 이름을 포함하도록 수정했다.

DBA 권한이 없는 일반 사용자가 "SHOW CREATE TABLE" 문을 수행하면 오류가 발생함 (CUBRIDSUS-11408)

csql -S -u public demodb -c "CREATE TABLE t1 (id INT, id2 INT) PARTITION BY HASH(id) PARTITIONS 2;"
csql -S -u public demodb -c "SHOW CREATE TABLE t1"

ERROR: select is not authorized on t1.

CentOS 6.3 이상의 Linux에서 입력 값을 포함하는 에러 메시지가 잘못 출력됨 (CUBRIDSUS-10940)

csql> ;column-width bbbbb= 100 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ERROR: Invalid argument(10aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa).

cubrid plandump의 출력 결과에 일부 계획이 누락됨 (CUBRIDSUS-9657)

수정 이후 추가한 정보는 다음과 같다.

  • 스캔 계획(scan plan) 출력 시 index scan keylimit 정보
  • 정렬 계획(sort plan) 출력 시 sort limit 여부
  • SELECT 문에 대한 계획 출력 시 skip order by
  • SELECT 문에 대한 계획 출력 시 skip group by

"cubrid applyinfo" 명령의 "-p" 옵션에 INT_MAX보다 큰 값을 주면 오류가 발생함 (CUBRIDSUS-12454)

"-p" 옵션의 값은 page ID이며, page ID는 64bit integer를 사용하므로 "-p" 옵션에 64bit integer 값을 허용하도록 수정했다.

DB 운영 중에도 "cubrid restoredb --list" 명령을 통해 백업 볼륨 정보를 보는 것이 가능하도록 수정 (CUBRIDSUS-8185)

수정 이전 버전에서 "cubrid restoredb --list" 명령은 데이터베이스가 운영 중이 아닐 때만 실행 가능하다.

Windows에서 broker_log_top 명령의 입력 인자에 *이 포함되는 경우 모든 이름을 뜻하는 패턴으로 인식하지 못함 (CUBRIDSUS-9903)

Windows에서 "broker_log_top .sql.log" 명령 실행 시 ".sql.log"를 a.sql.log, b.sql.log, ... 등의 파일 리스트로 인식하지 못하는 문제를 수정했다.

데이터 삭제가 빈번히 발생하는 환경에서 compactdb를 수행한 이후, 잘못된 페이지 할당으로 DB 볼륨에 이상(crash)이 발생할 수 있음 (CUBRIDSUS-12810)

데이터 삭제가 빈번히 발생하는 환경에서 compactdb를 수행한 이후, 이미 사용중인 페이지를 다시 할당하는 오동작으로 인해 DB볼륨에 이상(crash)이 발생할 수 있는 문제를 수정했다.

분할 테이블에 고유 인덱스가 존재할 때 "cubrid checkdb" 명령을 수행하면 데이터가 불일치한다는 오류 메시지가 출력됨 (CUBRIDSUS-13490)

CREATE TABLE foo (id INT, name STRING)
PARTITION BY RANGE(id)
(PARTITION before_2000 VALUES LESS THAN (2000),
PARTITION before_2008 VALUES LESS THAN (2008));
CREATE UNIQUE INDEX u_foo ON foo(id);
$cubrid checkdb testdb -S

Some inconsistencies were detected in your database.

"cubrid heartbeat stop" 명령의 수행 시 failover 시간 단축(CUBRIDSUS-12526)

수정 이전 버전에서는 "cubrid heartbeat stop" 명령의 실행을 시작하는 순간부터 종료될 때까지 DB 서버에 접속을 시도하는 사용자의 모든 요청이 대기 상태가 되어 failover 시간이 길어진다. 수정 이후 버전에서는 해당 명령이 수행되는 동안에도 사용자의 요청에 바로 응답하므로, failover 시간이 단축된다.

"cubrid copydb"의 "--lob-base-path" 옵션이 정상 동작하도록 수정 (CUBRIDSUS-12708)

"cubrid copydb" 명령 수행 시 LOB 데이터 파일의 저장소 위치를 지정하는 "--lob-base-path" 옵션이 명시되지 않으면 databases.txt 파일에 LOB 데이터 경로를 기록하지 않는 오류를 수정했다. 또한, "--lob-base-path" 옵션이 명시되면 해당 위치를 LOB 데이터 파일의 저장소 위치로 지정하는 기능이 정상 동작하지 않는 오류를 수정했다.

설정, 빌드 및 설치

외래 키 제약 조건에 의해 레코드가 삭제 또는 갱신될 때 cubrid.conf의 lock_timeout 파라미터 값 설정이 무시되는 현상 (CUBRIDSUS-13267)

CREATE TABLE t1
(
    a INT PRIMARY KEY
);

CREATE TABLE t2
(
  a INT PRIMARY KEY,
  b INT,
  c INT,
  FOREIGN KEY(b) REFERENCES t1(a) ON DELETE CASCADE
);

INSERT INTO t1 VALUES(1),(2);
INSERT INTO t2 VALUES(1,1,1), (2,2,2);

Client 1

// autocommit off
UPDATE t2 SET c=c+1 WHERE a=2;

Client 2

DELETE FROM t1 WHERE a=2;

수정 이전 버전에서는 lock_timeout에 의해 에러가 발생함에도 불구하고 Client 2의 질의가 성공적으로 수행된다.

access_ip_control_file의 IP 주소에 0이 포함되어 있으면 DB 서버 구동에 실패함 (CUBRIDSUS-12188)

cubrid.conf

access_ip_control=yes
access_ip_control_file=db.access

수정 이전 버전에서 아래 db.access 파일의 IP 주소에 0이 포함되면 DB 서버 구동에 실패한다.

db.access

[@TESTDB]
10.100.0.1

cubrid_broker.conf의 MIN_NUM_APPL_SERVER, MAX_NUM_APPL_SERVER 값이 서로 다른 경우 "cubrid broker status -b" 수행 결과 일부가 잘못 출력됨 (CUBRIDSUS-12562)

cubrid_broker.conf의 MIN_NUM_APPL_SERVER, MAX_NUM_APPL_SERVER 값이 서로 다른 경우 "cubrid broker status -b" 명령으로 출력되는 TPS, QPS, SELECT, INSERT, UPDATE, DELETE, OTHERS, #CONNECT 값들이 잘못되는 현상을 수정했다.

MIN_NUM_APPL_SERVER와 MAX_NUM_APPL_SERVER가 다른 경우 일부 CAS에 "cubrid broker reset" 명령이 적용되지 않음 (CUBRIDSUS-12516)

cubrid_broker.conf의 MIN_NUM_APPL_SERVER 값과 MAX_NUM_APPL_SERVER 값이 서로 다른 경우 일부 CAS에 "cubrid broker reset" 명령이 적용되지 않는 문제를 수정했다.

Windows에서 CUBRID_CHARSET 환경 변수를 명시하지 않으면 CUBRID 트레이 구동에 실패함 (CUBRIDSUS-12514)

CUBRID 트레이 구동 시 CUBRID_CHARSET 환경 변수의 설정 여부를 확인하지 않도록 수정했다. 참고로, CUBRID_CHARSET 환경 변수는 9.2 버전부터 더 이상 사용되지 않는다.

Ubuntu에서 소스 빌드에 실패함 (CUBRIDSUS-10963)

make 수행 시 libedit의 configure.ac 파일에서 오류가 발생하는 문제를 수정했다. 단, libncurses 패키지가 설치되어 있지 않은 경우 이를 설치해야 한다.

libedit sudo apt-get install libncurses5-dev

Windows 64 비트용 CUBRID 소스 코드 빌드 시 gencat.exe가 없다는 에러 메시지와 함께 실패함 (CUBRIDSUS-12370)

'"D:\code\win\x64\Debug"\..\..\gencat\gencat.exe' is not recognized as an internal or external command

로깅

broker와 DB 사이에 발생하는 에러 세분화 (CUBRIDSUS-12261)

broker와 DB 사이에 발생하는 핸드쉐이크(handshake) 에러 및 연결 에러를 세분화했다.

에러 원인에 따라 세분화된 에러 코드 및 에러 메시지는 다음과 같다.

  • handshake 관련 에러

    에러 원인 기존 에러 코드 기존 에러 메시지 새 에러 코드 새 에러 메시지
    브로커 ACCESS_MODE와 서버의 상태 (active/standby) 불일치 -743 Failed on handshake between client and server. (peer host ?) -1138 Handshake error (peer host ?): incompatible read/write mode. (client: ?, server: ?)
    ha_delay_limit을 설정한 서버에서 복제 지연 발생 -1139 Handshake error (peer host ?): HA replication delayed.
    레플리카만 접속 가능한 브로커(CAS)가 레플리카가 아닌 서버 접속 시도 -1140 Handshake error (peer host ?): replica-only client to non-replica server.
    HA maintenance 모드인 서버에 원격 접속 -1141 Handshake error (peer host ?): remote access to server not allowed.
    서버 버전 알 수 없음 -1142 Handshake error (peer host ?): unidentified server version.
  • 연결 관련 에러

    에러 원인 기존 에러 코드 기존 에러 메시지 새 에러 코드 새 에러 메시지
    cub_master 프로세스 down -353 Cannot make connection to master server on . host ?. -353 Cannot make connection to master server on host ?.
    장비 down -1143 Timed out attempting to connect to ?. (timeout: ? sec(s))

SQL 트레이스 출력 결과에서 인덱스 스캔의 힙 "lookup time" 시간이 실제보다 작은 값으로 출력됨 (CUBRIDSUS-12678)

csql> ;trace on
csql> SELECT a, b FROM x WHERE a < 10 and b = 'g';
...
Trace Statistics:
  SELECT (time: 925, fetch: 73745, ioread: 64532)
    SCAN (index: x.idx), (btree time: 921, fetch: 73742, ioread: 64532, readkeys: 9, filteredkeys: 9, rows: 9216) (lookup time: 85, rows: 1024)

잠금 타임아웃 이벤트 로그에 blocker의 SQL이 잘못 출력됨 (CUBRIDSUS-12713)

client 1
    csql> INSERT INTO x VALUES (4);
client 2
    csql> UPDATE x SET a = 10 WHERE a = 4;

위의 질의를 각 클라이언트에서 수행할 때 아래와 같이 blocker의 SQL이 실제 blocker SQL이 아닌 다른 SQL로 잘못 출력되는 현상을 수정했다.

12/19/13 18:37:57.304 - LOCK_TIMEOUT
waiter:
  client: PUBLIC@testhost|csql(10458)
  lock: U_LOCK (oid=0|560|4, table=x)
  sql: update [x] [x] set [x].[a]= ?:1 where [x].[a]= ?:0
  bind: 4
  bind: 10

blocker:
  client: PUBLIC@testhost|csql(10459)
  lock: X_LOCK (oid=0|560|4, table=x)
  sql: update [x] [x] set [x].[a]= ?:1 where [x].[a]= ?:0

주의 사항

신규 주의 사항

prefix 인덱스 기능 제거 예정(deprecated) (CUBRIDSUS-13222)

prefix 인덱스 기능은 제거될 예정이므로, 더 이상 사용을 권장하지 않는다.

FOR ORDERBY_NUM() 구문 제거 예정(deprecated) (CUBRIDSUS-13213)

FOR ORDERBY_NUM() 구문은 LIMIT 절이 대신할 수 있어 제거될 예정이므로, 더 이상 사용을 권장하지 않는다.

9.3 버전과 9.1 이하 버전의 DB 볼륨이 서로 호환 안 됨 (CUBRIDSUS-11316)

  • 9.3과 9.1

    9.2 DB 볼륨은 9.3 DB 볼륨과 호환되지만, 9.2 DB 볼륨과 9.1 DB 볼륨은 호환되지 않으므로 CUBRID 9.1을 9.3으로 업그레이드하는 사용자는 CUBRID 9.3 설치 이후 기존의 DB 볼륨을 9.3용으로 반드시 변환해야 한다. 볼륨 마이그레이션을 위해서 9.3 버전에 제공되는 migrate_91_to_92 유틸리티를 제공한다.

    % migrate_91_to_92 <db_name>
    

    Note

    9.1 버전 및 그 이전 버전 사용자는 데이터를 마이그레이션하는 것과 함께 드라이버, 브로커, DB 서버 모두를 반드시 업그레이드해야 한다.

  • 9.3과 2008 R4.4 이하

    2008 R4.4 이하 버전과 DB 볼륨이 호환되지 않으므로 cubrid unloaddb/loaddb를 이용하여 데이터를 마이그레이션해야 한다. 보다 자세한 사항은 업그레이드를 참고한다.

보다 자세한 사항은 업그레이드를 참고한다.

기본 설정에서 정렬 병합 조인(sort merge join) 계획이 적용되지 않음(CUBRIDSUS-13186)

SELECT /*+ USE_MERGE */  DISTINCT h.host_year, o.host_nation
FROM history h LEFT OUTER JOIN olympic o ON h.host_year = o.host_year AND o.host_year > 1950;

일반적으로 정렬 병합 조인 계획이 적용되지 않는 것이 성능 상 유리하므로, 9.3 버전부터는 기본 설정에서 정렬 병합 조인 계획이 생성되지 않도록 수정했다.

단, USE_MERGE 힌트를 명시하거나 cubrid.conf의 optimizer_enable_merge_join 값을 yes로 설정하면 수정 이전과 마찬가지로 정렬 병합 조인(sort merge join) 계획이 질의 계획 후보에 포함될 수 있다.

기존 주의 사항

9.2부터 CUBRID_CHARSET 환경 변수 제거

데이터베이스 생성 시에 로캘을 지정하도록 변경됨으로 인하여 9.2부터는 CUBRID_CHARSET 환경변수는 더 이상 사용되지 않는다. 따라서 데이터베이스 생성 시 로캘을 지정해야 한다.

[JDBC] 2008 R4.4부터 연결 URL의 zeroDateTimeBehavior 속성 값이 "round"일 때 TIMESTAMP의 zero date가 '0001-01-01 00:00:00'에서 '1970-01-01 00:00:00'(GST)로 변경됨 (CUBRIDSUS-11612)

2008 R4.4부터, 연결 URL의 zeroDateTimeBehavior 속성 값이 "round"일 때 TIMESTAMP의 zero date 값이 '0001-01-01 00:00:00'에서 '1970-01-01 00:00:00'(GST)로 변경되었으므로, 응용 프로그램에서 zero date를 사용하는 경우 주의해야 한다.

9.2부터 AIX용 CUBRID를 SH 패키지로 설치 시 권장 사항 (CUBRIDSUS-12251)

AIX OS에서 ksh를 사용하여 CUBRID SH 설치 패키지를 설치하는 경우, 다음의 경고 메시지와 함께 실패하므로,

0403-065 An incomplete or invalid multibyte character encountered.

CUBRID SH 설치 패키지를 실행하려면 ksh 대신 ksh93 또는 bash를 사용할 것을 권장한다.

$ ksh93 ./CUBRID-9.2.0.0146-AIX-ppc64.sh
$ bash ./CUBRID-9.2.0.0146-AIX-ppc64.sh

9.1부터 CUBRID_LANG 환경 변수 제거, CUBRID_MSG_LANG 환경 변수 추가

9.1 버전부터 CUBRID_LANG 환경 변수는 더 이상 사용되지 않는다. 유틸리티 메시지 및 오류 메시지를 출력할 때는 CUBRID_MSG_LANG 환경 변수를 사용한다.

2008 R4.3, 9.1부터 CCI 응용 프로그램에서 여러 개의 질의를 한 번에 수행한 결과의 배열에 대한 에러 처리 방식 수정 (CUBRIDSUS-9364)

CCI 응용에서 여러 개의 질의를 한 번에 수행할 때 2008 R3.0부터 2008 R4.1 버전까지는 cci_execute_array 함수, cci_execute_batch 함수 또는 cci_execute_result 함수에 의한 질의 수행 결과들 중 하나만 에러가 발생해도 해당 질의의 에러 코드를 반환했으나, 2008 R4.3 버전 및 9.1 버전부터는 전체 질의 개수를 반환하고 CCI_QUERY_RESULT_* 매크로들을 통해 개별 질의에 대한 에러를 확인할 수 있도록 수정했다.

수정 이전 버전에서는 에러가 발생한 경우에도 배열 내 각각의 질의들의 성공 실패 여부를 알 수 없으므로, 이를 판단해야 한다.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);

if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);

    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...

수정 이후 버전에서는 에러가 발생하면 전체 질의가 실패한 것이며, 에러가 발생하지 않은 경우에 대해 배열 내 각 질의들의 성공 실패 여부를 판단한다.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);
if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
  }
else
  {
    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...

javax.sql.XAConnection 인터페이스에서 HOLD_CURSORS_OVER_COMMIT 미지원 (CUBRIDSUS-10800)

CUBRID는 현재 javax.sql.XAConnection 인터페이스에서 ResultSet.HOLD_CURSORS_OVER_COMMIT을 지원하지 않는다.

9.0부터 STRCMP는 대소문자를 구분하여 문자열을 비교함

9.0 이전 버전까지는 STRCMP가 대소문자를 구분하지 않고 문자열을 비교했으나, 9.0 버전부터는 대소문자를 구분하여 문자열을 비교한다. STRCMP가 대소문자를 구분하지 않고 동작하게 하려면 문자열에 대소문자를 구분하지 않는 콜레이션(예: utf8_en_ci)을 지정해야 한다.

-- In previous version of 9.0 STRCMP works case-insensitively
SELECT STRCMP ('ABC','abc');
0

-- From 9.0 version, STRCMP distinguish the uppercase and the lowercase when the collation is case-sensitive.
-- charset is en_US.iso88591

SELECT STRCMP ('ABC','abc');
-1

-- If the collation is case-insensitive, it distinguish the uppercase and the lowercase.
-- charset is en_US.iso88591

SELECT STRCMP ('ABC' COLLATE utf8_en_ci ,'abc' COLLATE utf8_en_ci);
0

2008 R4.1부터 CCI_DEFAULT_AUTOCOMMIT 의 기본값이 ON으로 바뀜 (CUBRIDSUS-5879)

2008 R4.1 버전부터 CCI 인터페이스로 개발된 응용 프로그램의 자동 커밋 모드에 영향을 주는 브로커 파라미터인 CCI_DEFAULT_AUTOCOMMIT의 기본값이 ON으로 변경되었다. 따라서 CCI 및 CCI로 개발된 인터페이스(PHP, ODBC, OLE DB 등) 사용자는 응용 프로그램의 자동 커밋 모드가 이에 적합한지 살펴보아야 한다.

2008 R4.0부터 페이지 단위의 옵션 및 파라미터가 볼륨 크기 단위로 바뀜 (CUBRIDSUS-5136)

cubrid createdb 유틸리티의 DB 볼륨 크기 및 로그 볼륨 크기를 지정할 때 페이지 단위를 사용하는 옵션들(-p, -l, -s)은 제거될 예정이므로, 2008 R4.0 Beta 이후 새로 추가된 옵션들(--db-volume-size, --log-volume-size, --db-page-size, --log-page-size)을 사용한다.

cubrid addvoldb 유틸리티의 DB 볼륨 크기를 지정하는 경우에도 페이지 단위를 사용하지 않고 2008 R4.0 Beta 이후 새로 추가된 옵션(--db-volume-size)을 사용한다. 페이지 단위의 시스템 파라미터들은 추후 제거될 예정이므로 바이트 단위의 새로운 시스템 파라미터를 사용할 것을 권장한다. 관련 시스템 파라미터들에 대한 내용은 아래를 참고한다.

2008 R4.0 Beta 이전 사용자는 DB 볼륨 크기 설정 시 주의 (CUBRIDSUS-4222)

2008 R4.0 Beta 버전부터 DB 생성 시 데이터 페이지 및 로그 페이지의 크기 기본값이 4KB에서 16KB로 변경되었으므로, DB 볼륨을 페이지 개수로 지정하여 생성하는 경우 볼륨의 바이트 크기가 기대와 다를 수 있음에 주의한다. 아무런 옵션도 주지 않을 경우 이전 버전에서는 4KB의 페이지 크기로 100MB의 DB 볼륨을 생성했으나, 2008 R4.0 버전부터는 16KB의 페이지 크기로 512MB의 DB 볼륨을 생성하게 된다.

그리고, DB 볼륨의 생성 가능한 최소 크기를 20MB로 제한했으므로 이보다 작은 크기의 DB 볼륨은 생성할 수 없다.

2008 R4.0 이전 버전의 일부 시스템 파라미터들의 기본값 변경 (CUBRIDSUS-4095)

2008 R4.0부터 다음 시스템 파라미터들의 기본값이 변경되었다.

DB 서버가 허용하는 동시 연결 개수를 설정하는 max_clients의 기본값, 인덱스 페이지 생성 시 향후 업데이트를 대비하여 확보하는 여유 공간 비율을 설정하는 index_unfill_factor의 기본값이 변경되었으며, 바이트 단위 시스템 파라미터의 기본값이 기존 페이지 단위 시스템 파라미터의 기본값보다 커져서 별도의 설정을 하지 않는 경우 더 많은 메모리를 사용하게 되었다.

기존 시스템 파라미터 추가된 시스템 파라미터 기존 기본값 변경된 기본값 (단위: 바이트)
max_clients 없음 50 100
index_unfill_factor 없음 0.2 0.05
data_buffer_pages data_buffer_size 100M(페이지 크기=4K) 512M
log_buffer_pages log_buffer_size 200K(페이지 크기=4K) 4M
sort_buffer_pages sort_buffer_size 64K(페이지 크기=4K) 2M
index_scan_oid_buffer_pages index_scan_oid_buffer_size 16K(페이지 크기=4K) 64K

또한, cubrid createdb로 DB 생성 시 데이터 페이지 크기와 로그 페이지 크기의 최소값이 1K에서 4K로 변경되었다.

시스템 파라미터를 잘못 설정하면 DB 서비스, 유틸리티 및 응응 프로그램이 구동되지 않음 (CUBRIDSUS-5375)

cubrid.conf 또는 cubrid_ha.conf에 정의되지 않은 시스템 파라미터를 설정하거나, 페이지 단위의 시스템 파라미터와 바이트 단위의 시스템 파라미터가 동시에 사용되거나, 시스템 파라미터 값이 허용 범위를 벗어나면 이와 관련된 DB 서비스, 유틸리티 및 응응 프로그램이 구동되지 않는다.

CUBRID 32bit 버전에서 data_buffer_size에 2G를 초과하는 값을 설정하면 DB 구동에 실패함 (CUBRIDSUS-5349)

CUBRID 32bit 버전에서 data_buffer_size가 2G를 초과하는 값으로 설정되는 경우 DB 구동에 실패한다. 32bit 버전에서는 OS의 한계로 인해 설정값이 2G를 초과할 수 없음에 주의한다.

Windows Vista 이상 버전에서 CUBRID 유틸리티를 사용한 서비스 제어 시 권장 사항 (CUBRIDSUS-4186)

Windows Vista 이상 버전에서 cubrid 유틸리티를 사용하여 서비스를 제어하려면 명령 프롬프트 창을 관리자 권한으로 구동한 후 사용하는 것을 권장한다.

명령 프롬프트 창을 관리자 권한으로 구동하지 않고 cubrid 유틸리티를 사용하는 경우 UAC(User Account Control) 대화 상자를 통하여 관리자 권한으로 수행될 수 있으나 수행 결과 메시지를 확인할 수 없다.

Windows Vista 이상 버전에서 명령 프롬프트 창을 관리자 권한으로 구동하는 방법은 다음과 같다.

  • [시작> 모든 프로그램> 보조 프로그램> 명령 프롬프트]에서 마우스 오른쪽 버튼을 클릭한다.
  • [관리자 권한으로 실행(A)]을 선택하면 권한 상승을 확인하는 대화 상자가 활성화되고, "예"를 클릭하여 관리자 권한으로 구동한다.

CUBRID 소스 빌드 후 실행 시, 매니저 서버 프로세스 관련 오류 발생 (CUBRIDSUS-3553)

사용자가 직접 빌드하여 설치하는 경우, CUBRID와 CUBRID 매니저를 각각 빌드하여 설치해야 한다. 만약, CUBRID 소스만 checkout하여 빌드 후 cubrid service start 또는 cubrid manager start를 실행하면, "cubrid manager server is not installed"라는 오류가 발생한다.

2008 R3.0 이하 버전에서 사용하던 GLO 클래스 지원 중단 (CUBRIDSUS-3826)

CUBRID 2008 R3.0 이하 버전은 glo (Generalized Large Object) 클래스를 사용하여 Large Object를 처리했으나, CUBRID 2008 R3.1 이상 버전 glo 클래스를 제거하고 BLOB, CLOB 타입(이하 LOB)을 지원한다. LOB 데이터 타입에 대한 자세한 내용은 BLOB/CLOB 데이터 타입 절을 참고하면 된다.

기존의 glo 클래스 사용자는 다음과 같이 작업할 것을 권장한다.

  • GLO 데이터를 파일로 저장한 후 어플리케이션 및 DB 스키마에서 GLO를 사용하지 않도록 수정한다.
  • unloaddb, loaddb 유틸리티를 이용하여 DB 마이그레이션을 한다.
  • 변경한 어플리케이션에 맞게 파일을 LOB 데이터로 로딩하는 작업을 수행하도록 한다.
  • 수정한 어플리케이션이 정상 동작하는지 확인한다.

참고로, cubrid loaddb 유틸리티는 GLO 클래스를 상속받거나 GLO 클래스 타입을 가진 테이블을 로딩하려는 경우 " Error occurred during schema loading " 오류 메시지와 함께 데이터 로딩을 중지한다.

GLO 클래스의 지원 중단에 따라 각 인터페이스 별로 삭제한 함수는 다음과 같다.

인터페이스 삭제한 함수
CCI

cci_glo_append_data

cci_glo_compress_data

cci_glo_data_size

cci_glo_delete_data

cci_glo_destroy_data

cci_glo_insert_data

cci_glo_load

cci_glo_new

cci_glo_read_data

cci_glo_save

cci_glo_truncate_data

cci_glo_write_data

JDBC

CUBRIDConnection.getNewGLO

CUBRIDOID.loadGLO

CUBRIDOID.saveGLO

PHP

cubrid_new_glo

cubrid_save_to_glo

cubrid_load_from_glo

cubrid_send_glo

마스터 프로세스와 서버 프로세스 간 프로토콜 변경 및 두 개 버전을 동시에 운영하는 경우 포트 설정 필요 (CUBRIDSUS-3564)

마스터 프로세스(cub_master)와 서버 프로세스(cub_server) 간 통신 프로토콜 변경으로 인해 CUBRID 2008 R3.0 이상 버전의 마스터 프로세스는 하위 버전의 서버 프로세스와 통신할 수 없고, 하위 버전의 마스터 프로세스도 2008 R3.0 이상 버전의 서버 프로세스와 통신할 수 없다. 따라서, 이미 하위 버전이 설치되어 있는 환경에서 새 버전을 추가 설치하여, 두 개 버전의 CUBRID를 동시에 운영하는 경우 각각 서로 다른 포트를 사용하도록 cubrid.conf의 cubrid_port_id 시스템 파라미터를 수정해야 한다.

JDBC에서 연결 정보를 URL 스트링으로 입력하는 경우 물음표를 반드시 명시 (CUBRIDSUS-3217)

JDBC에서 URL 스트링으로 연결 정보를 입력하는 경우 이전 버전에서는 물음표(?)를 입력하지 않더라도 속성(PROPERTY) 정보가 적용되었으나, CUBRID 2008 R3.0부터는 문법에 따라 반드시 물음표를 명시해야 하고 이를 생략할 경우 에러를 출력한다. 또한, 연결 정보 중 USERNAME과 PASSWORD가 없더라도 반드시 콜론( : )을 명시해야 한다.

URL=jdbc:CUBRID:127.0.0.1:31000:db1:::altHosts=127.0.0.2:31000,127.0.0.3:31000 -에러 처리
URL=jdbc:CUBRID:127.0.0.1:31000:db1:::?altHosts=127.0.0.2:31000,127.0.0.3:31000 -정상 처리

DB 이름에 @를 포함할 수 없음 (CUBRIDSUS-2828)

DB 이름에 @이 포함되는 경우 호스트 이름이 명시된 것으로 해석될 수 있으므로 이를 방지하기 위하여 cubrid createdb, cubrid renamedb, cubrid copydb 유틸리티 실행 시 DB 이름에 @를 포함할 수 없도록 수정했다.