[ ORACLE에서의 자료형 VARCHAR2, CLOB 사용 및 가공시 주의점 ]

보통 4000bytes 이하의 문자열에 사용되는 VARCHAR2

대용량 데이터 LOB 의 문자자료형인 CLOB 데이터

 

 

[ Charset 에 따른 한글 문자 bytes 크기 ]

ORACLE 의 권장 character set 은 UTF-8 이며, UTF-8 은 문자 하나에 최대 4bytes.

* 한글은 UTF-8 에서 문자 하나당 3bytes, EUC-KR 에서 문자 하나당 2bytes

* SQL에서 VARCHAR2 는 최대 4000bytes 길이 제한.

 

※ DB charset 확인하는 방법

1) 설정확인(권장)

SELECT name, value$
FROM sys.props$
WHERE name = 'NLS_CHARACTERSET';

2) 문자를 조회하여 확인

SELECT LENGTHB('일') FROM DUAL;

결과로 리턴되는 BYTES 크기 확인

* LENGTHB 는 BYTES 크기 반환

 

아래와 같이 TABLE 생성시 

CREATE TABLE sample.persons(
    name VARCHAR2(9) NOT NULL,
    PRIMARY KEY(name)
);

VARCHAR2(9) 의 9은 bytes 를 의미하며 UTF-8 기준으로 한글은 3글자밖에 들어갈 수 없다.

 

 

[ VARCHAR2 칼럼에 데이터 넣기 ]

1. Query 에서 잘라 넣기

1) SUBSTR 사용하여 CHAR 문자 잘라 넣기

INSERT INTO persons VALUES (SUBSTR('네자이름'), 1, 3));

* SUBSTR 은 문자 length 를 기준으로 자름

* TABLE DESC 에 명시된 자료형의 크기는 default가 bytes 기준이므로 CHAR length를 기준으로 위와 같이 문자열을 잘라넣는건 부적절.

 

2) SUBSTRB 사용하여 BYTES 단위로 문자 잘라 넣기

INSERT INTO persons VALUES (SUBSTRB('네자이름'), 1, 9));

* SUBSTRB 는 문자 bytes 를 기준으로 자름

* 위와같이 데이터를 넣을 경우 bytes단위로 문자열이 잘려나가기 때문에 한글이 깨질 수 있으므로 부적절.

 

※ 또 다른 문제.

SQL에서 VARCHAR2 는 최대 4000bytes 길이 제한이 있어

1), 2) 에서 사용된 SUBSTR, SUBSTRB 함수 모두 input 값이 4000bytes 가 넘을시 "ORA-01704: 문자열이 너무 깁니다" 에러가 발생한다.

 

2. 소스레벨에서 BYTES 단위로 잘라 넣기

정해진 bytes 크기의 한도내에서 한글이 깨지지 않게 문자열 자르기

SQL 에서 문자열을 가공하기보단 소스레벨에서 가공

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static String subStrByte(String str, int cutlen){
        if(!str.isEmpty()){
            str = str.trim();
            if(str.getBytes().length <= cutlen) {
                return str;
            }else{
                StringBuffer sbStr = new StringBuffer(cutlen);
                int nCnt = 0;
                for(char ch: str.toCharArray()){
                    nCnt += String.valueOf(ch).getBytes().length;
                    if(nCnt > cutlen) break;
                    sbStr.append(ch);
                }
                return sbStr.toString();
            }
        } else {
            return "";
        }
    }
cs

 

[ CLOB 데이터 읽기 및 가공하기 ]

CLOB 데이터는 LENGTH, LENGTHB, SUBSTRB 함수 등을 지원하지 않음.

 

VARCHAR2 데이터에서 사용가능한 함수 사용을 위해 VARCHAR2 로 변환하고자 할 경우,

DBMS_LOB.SUBSTR(clob칼럼, 가져올길이, offset)을 사용하여 VARCHAR2 로 변환이 가능

* CLOB 데이터 가공시 SUBSTR 보다 DBMS_LOB.SUBSTR 의 퍼포먼스가 뛰어남 (참고)

* DBMS_LOB.SUBSTR() 사용시에도 4000bytes 를 넘는 데이터를 가져오지 않도록 주의 해야한다

 

※ 또 다른 문제.

temp segment 가 unrelease 되는 현상.

CLOB 칼럼에 함수를 직접 사용할 경우, 메모리와 같은 역할을 하는 temp segment를 사용하게 되며 release 하지 않고 쌓일 수 있다. 이는 서버 장애를 유발하여 서비스 전체에 영향을 줄 수 있다.

실제로 이와 관련하여, 운영중인 DB서버 전체가 마비되어 서비스 장애를 경험해 보았다..

=> CLOB 칼럼에 함수 사용은 지양하자. 소스레벨에 그대로 가져와서 소스레벨에서 자르는 걸 권장.

 

[ 관련에러 ]

ORA-01704: 문자열이 너무 깁니다

ORA-64203: 문자 집합 변환 후 대상 버퍼가 너무 작아 CLOB 데이터를 보유할 수 없습니다.

ORA-06502: 문자열 버퍼가 너무 작습니다.

 

참고 :

https://tomining.tistory.com/95

 

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03

1. CLOB 을 읽을 때 4000bytes 가 넘을 경우 java 단에서 메모리 부족으로 에러가 발생한다.

2. DBMS_LOB.SUBSTR을 사용하여 4000bytes 이하로 데이터를 잘라서 가져올 수 있다 (CLOB 데이터는 VARCHAR2로 바뀐다)

3. CLOB 칼럼에 함수를 씌우거나 "||" 를 사용하여 문자를 붙이는 등의 작업이 DB query 에서 이뤄질 경우 temp segment 에 CLOB 데이터 크기만큼 공간을 차지하게 된다.

4. order by 등과 다르게 CLOB 으로 인한 TEMP segment 공간은 session이 끝날때 까지 제거되지 않는다.

5. TEMP space 가 꽉 차게 되면 타 서비스에 영향을 주게 된다

 

SUBSTR 을 사용하지 않고 CLOB 데이터를 그대로 읽어오면 TEMP SEGMENT 가 full 차는 현상은 방지할 수 있지만

CLOB 데이터의 크기가 4000bytes 가 넘을 경우 자바에서 읽어올 수 없다.

 

해결방법은

1. CLOB 데이터를 temp segment 에서 release 해줄 수 있도록 alter session ~ 을 SUBSTR(CLOB,...) 쿼리와 함께 호출.

2. java 에서 clob 데이터에 대한 release 처리를 해준다.

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] VARCHAR2, CLOB 사용 및 가공시 주의점  (1) 2021.07.21
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03

 

 

 

SELECT A.STATUS        -- 상태정보

      ,A.SID           -- SID 

      ,A.SERIAL#       -- 시리얼번호 

      ,A.USERNAME      -- 유저 

      ,A.OSUSER        -- OS 사용자

      ,B.SQL_TEXT      -- 쿼리

  FROM V$SESSION A

      ,V$SQLAREA B

 WHERE A.SQL_HASH_VALUE = B.HASH_VALUE 

   AND A.SQL_ADDRESS = B.ADDRESS 

   AND A.STATUS = 'ACTIVE'



taking.co.kr/96

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] VARCHAR2, CLOB 사용 및 가공시 주의점  (1) 2021.07.21
[ORACLE] CLOB BLOB  (0) 2021.04.14
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03

로컬 ORACLE 설치 bit 확인

 

www.overtop.co.kr/279

 

 

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03
프로시저 호출 방법 : 파라미터가 있는 경우, mybatis에서의 호출  (0) 2020.10.26

* 현재시각 2021/02/08 17시일때

select * from where tdate > sysdate-1;
: 2/7 17시 이후 데이터

select * from where trunc(tdate) > trunc(sysdate)-1;
: 2/8 0시 이후 데이터

select * from where tdate > trunc(sysdate)-1;
: 2/7 0시 이후 데이터

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
LEAD, LAG  (0) 2021.02.03
프로시저 호출 방법 : 파라미터가 있는 경우, mybatis에서의 호출  (0) 2020.10.26

LEAD

다음행읽기

 

LAG

이전행읽기

 

gent.tistory.com/339

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
프로시저 호출 방법 : 파라미터가 있는 경우, mybatis에서의 호출  (0) 2020.10.26

MS SQL

EXEC procedure();

 

그외 ORACLE, MYSQL 등

CALL procedure();

EXEC vs CALL 차이

 

 

리턴(out) 파라미터가 있는 경우 프로시저 호출 방법

DECLARE
var aa VARCHAR(10);
var bb VARCHAR(10);
BEGIN
CALL PROCEDURE(
aa,
bb,
param
);
END;

 

Mybatis xml 에서의 프로시저 호출 방법

{CALL SEND_PROC(#{retCd, jdbcType=NUMERIC, mode=OUT},
                         #{retMsg, jdbcType=VARCHAR, mode=OUT},
                         #{flag, jdbcType=VARCHAR, mode=IN},
                         #{msg, jdbcType=VARCHAR, mode=IN},
                         #{tel, jdbcType=VARCHAR, mode=IN},
                         #{id, jdbcType=VARCHAR, mode=IN},
                         TO_CHAR(SYSDATE +
                                      (#{seq, jdbcType=NUMERIC, mode=IN}) * 10 / (24*60*60),                                                                    'YYYYMMDDHH24MISS') ,'')
}

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03

MySQL 에서 일반적으로 사용되는 스토리지엔진은 MyISAM 과 InnoDB이다.

MyISAM이 default 스토리지엔진으로 사용된다.

각각의 스토리지엔진은 아래와 같은 장단점이 존재한다.

 

MyISAM

트랜잭션 지원 하지 않음

테이블 단위로 데이터가 저장된다

로우레벨 lock의 지원되지 않음

무결성이 보장되지 않음

table 퍼포먼스 속도가 InnoDB보다 빠르다

소규모 프로젝트에 적합하다. 

 

InnoDB

로우 레벨 lock 을 지원하며 이에따라 insert/update 성능이 MyISAM 보다 뛰어나다.

ACID (Atomicity, Consistency, Isolation and Durability) 속성을 제공한다.

외래키(Foreign Key)를 지원한다.

FullText 인덱싱 지원을 하지 않는다.

* FullText 인덱싱 : 값 전체를 인덱스로 사용

* table 단위의 데이터 저장이 아니기 때문에 SELECT COUNT(*) FROM table 은 전체테이블 rows를 스캔하게 된다.

  반면 MyISAM 은 table 단위로 저장되므로 이같은 경우엔 강점이 있다.

 

출처: What are the main differences between INNODB and MyISAM

 

 

※ MyISAM 은 어떻게 읽어야 할까?

https://lists.mysql.com/mysql/204267

 

 

 

 

반응형

'DB' 카테고리의 다른 글

데이터베이스 격리 수준 : Database Isolation level  (0) 2020.03.20

1. 데이터베이스 Isolation Level 이란

트랜잭션에서 일관성 없는 데이터를 허용하는 수준

 

 

2. Isolation Level 의 종류

- Read Uncommitted

- Read Commited

- Repeatable Read

- Serializable

Read Uncommitted -> Serializable 로 갈 수록 격리수준이 높다(high)

Serializable -> Read Uncommitted 로 갈 수록 격리수준이 낮다(low)

1) Read Uncommitted
- SELECT 문장 수행시 해당 데이터에 Shared Lock 이 걸리지 않는 Level
- 아직 commit 되지 않은 트랜잭션 A 의 데이터를 B가 SELECT 할 수 있음
발생하는 문제 : dirty read, non-repeatable read, phantom read

2) Read Commited
- Select 문장이 수행되는 동안 데이터에 Shared Lock 이 걸린다
- 아직 commit 되지 않은 트랜잭션 A 의 데이터를 B가 SELECT 할 수 없다
발생하는 문제 : non-repeatable read, phantom read

3) Repeatable Read
- 트랜잭션 A가 시작되기 전에 커밋된 내용까지만 조회할 수 있다.
- 자신의 트랜잭션 보다 낮은 트랜잭션에서 커밋된 것만 읽는다.
(모든 InnoDB의 트랜잭션은 고유한 트랜잭션 시퀀스를 가지고 있으며 Undo 영역에 백업된 모든 레코드는 변경을 발생시킨 트랜잭션의 번호가 포함되어 있다)
발생하는 문제 : phantom read

4) Serializable
- 트랜잭션이 완료될 때까지 다른 트랜잭션이 해당되는 영역에 대한 수정 및 입력을 할 수 없다.
- 완벽한 LOCK 을 건다.

 

3. 격리 수준에 따라 나타나는 현상

3-1) Dirty Read

1) 트랜잭션 A 에서 값을 넣는다. insert into user (seq, gender, name) values (1, 'M', 'pyo');

2) 트랜잭션 B 에서 값을 읽는다. select * from user where seq = 1;

3) 트랜잭션 A 에서 insert 했던 값을 롤백한다. 

4) 트랜잭션 B 에서 읽어놓은 값은 실제로 DB에 존재하지 않는 데이터가 돼버린다. (dirty 하다)

 

3-2) Non-repeatable Read

1) 트랜잭션 A 에서 값을 읽는다. select gender, name from user where seq = 1;

    result : M pyo

2) 트랜잭션 B 에서 값을 넣는다. update user set gender = 'W' where seq = 1;

3) 트랜잭션 B 에서 commit 한다.

4) 트랜잭션 A 에서 값을 읽는다. select gender, name from user where seq = 1;

    result : W pyo

    남자였던 pyo 가 여자가 되었다. 위처럼 반복해서 동일한 데이터를 읽을 경우 상이한 결과가 나온다.

 

3-3) Phantom Read

1) 트랜잭션 A 에서 범위(range) 기준으로 값을 읽는다.

2) 트랜잭션 B 에서 1)에 포함되는 값을 넣는다.

3) 트랜잭션 B 에서 commit 한다.

4) 트랜잭션 A 에서 범위(range) 기준으로 값을 읽는다.

   result : 1)에서 읽히지 않은 값이 결과로 나온다 

 

Isolation Level Dirty Read NonRepeatable Read Phantom Read
Read Uncommitted Permitted Permitted Permitted
Read Commited - Permitted Permitted
Repeatable Read - - Permitted
Serializable - - -

 

 Non-repeatable read vs Phantom read

Non-repeatable read 와 Phantom read 의 차이

 

※ 엔진별 Default Isolation Level

- Mysql InnoDB 엔진 : Repeatable-Read 

- Oracle : Read-Commited

 

 

4. isolation level 지정하기

1) sql에서의 isolation level 지정

SET TRANSACTION ISOLATION LEVEL 
   { READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE }

2) spring transaction 에서의 isolation level 지정

예제 참고

 

 

참고 :

영문으로 되어 있는 설명

그림으로 설명이 잘 되어 있는 곳

sql 코드로 설명이 잘 되어 있는 곳

mysql 공식문서

 

반응형

'DB' 카테고리의 다른 글

[DB] InnoDB vs MyISAM : InnoDB와 MyISAM의 차이점  (0) 2020.08.18

1. mysql-server 설치

>sudo apt-get update  //apt-get 업데이트

>sudo apt-get install mysql-server  //mysql-server 설치

 

2. /etc/mysql/ 밑의 conf 에서

binding ip 0.0.0.1 로 수정하여 외부에서도 접속 가능토록 수정

 

3. 실행 및 종료

>sudo /etc/init.d/mysql restart //재시작

>sudo systemctl start mysql //시작

>sudo systemctl enable mysql //서버 재시작시 mysql 자동 시작되도록 등록)

>sudo systemctl stop mysql

 

4. 유저 관리 및 DB 권한 주기

3-1) 데이터베이스 생성

>mysql -u root -p //root 로 접속

>CREATE DATABASE bootmybatis; //bootmybatis 이름으로 database 생성

>SHOW DATABASES; //databases 목록 조회

※ 유저 삭제

>DROP DATABASE dbname;

 

3-2) 유저 생성 및 접근 허용 IP 지정

>CREATE USER 'developyo'@'%' IDENTIFIED BY 'password';

//암호를 'password'로 하는 developyo 계정을 생성, 해당 사용자는 어떤 ip 에서도('%') 접속이 가능

>ALTER USER ''root'@'localhost' IDENTIFIED BY 'password';

//암호를 'password'로 하는 root 계정을 수정, 해당 사용자는 localhost에서만 접속이 가능

>FLUSH PRIVILEGES;  //commit

>SELECT user, host, password FROM mysql.user; //유저, 접근허용ip, 암호 확인

※ 유저 삭제

>DROP USER 'id'@'host';

 

3-3) 데이터베이스에 권한 부여

>GRANT ALL PRIVILEGES ON bootmybatis.* to developyo@'%';

>FLUSH PRIVILEGES;  //commit

>SHOW GRANTS FOR 'developyo'@'%'; //developyo 갖고있는 권한 확인

 

 

[호스트(window)에서 vm 게스트(우분투) mysql 에 접속하기]

1) NAT 설정 브릿지로 바꾸기

설정(settings) > 네트워크(network) > 다음에 연결됨 : 어댑터에 브리지 (attached to: Bridged Adapter) 로 변경

2) 터미널에서 ip 확인

>ifconfig 

3) mysql client 에서 위의 ip로 연결

 

참고 :

https://dejavuqa.tistory.com/317

https://bugwhale.com/virtualbox-bridged-adapter-error/

 

반응형

+ Recent posts