레이블이 Oracle인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Oracle인 게시물을 표시합니다. 모든 게시물 표시

DB Table Lock 걸기

멀티 쓰레드 환경에서 다수의 DB 커넥션이 테이블 값에 접근하여 쿼리를 수행하려 할때
발생할 수 있는 동시성을 해결하기 위한 방법 중 하나로 "for update" 구문을 사용할 수 있다.

/* 이미 Lock을 걸어 수행 중인 쿼리가 있으면 대기한다. */
select * from table_a for update;

/* 이미 Lock을 걸어 수행 중인 쿼리가 있으면 3초까지만 대기하고 빠져 나온다.(오라클) */
select * from table_a for update wait 3;

/* 이미 Lock을 걸어 수행 중인 쿼리가 있으면 대기하지 않고 바로 빠져 나온다.(오라클) */
select * from table_a for update no wait;


/*
예를 들어 다음 데이터가 들어갈 시퀀스 값을 알고 싶은 경우,
Oracle 의 경우 nextval 기능을 사용하면 다음 시퀀스 값을 유니크하게 얻어 오지만
MySQL 에는 nextval 이 없어 for update 구문을 이용하도록 한다.
*/
select ifnull(max(my_seq+1),1) from table_a for update;


DB 커넥션 끊김 방지하기

보통 DB에서는 쿼리 요청이 없는 Connection 은 일정시간이 지나면 끊어 버린다.

# MySQL 경우 기본 커넥션유지는 interactive_timeout 28800 (8시간)이다.
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_interactive_timeout
# 각종 타임 아웃 시간 보기
# 대기시간(연결 유지)은 wait_timeout
show variables like '%timeout%';

따라서 일정 주기만 커넥션을 유지를 위한 더미 쿼리(ex "Select 1;")를 요청해주도록 한다.
아니면 각 DB 마다 연결끊김 에러코드를 인지하여 다시 연결하도록 한다.

oracle
ORA-00028: your session has been killed
ORA-01012: not logged on
ORA-01033: ORACLE initialization or shutdown in progress
ORA-01034: ORACLE not available
ORA-01089: immediate shutdown in progress - no operations are permitted
ORA-03113: end-of-file on communication channel
ORA-03114: not connected to ORACLE
ORA-03127: no new operations allowed until the active operation ends
ORA-12571: TNS:packet writer failure

mssql
10054 : Connection Reset By peer (tcp 의 RST 로 비정상 종료로 연결을 끊는 경우)
10061 : Network Error

mysql
2003 : Can't connect to MySQL server
2013 : Lost connection to MySQL server during query
2006 : MySQL server has gone away


ODBC 사용시 각 DBMS 별 Connection String

ODBC 사용시 각 DBMS 별 Connection String

Oracle
Driver={Microsoft ODBC for Oracle};Server=10.10.10.10;Port=3306;Uid=ysoftman;Pwd=abcd1234;

MySQL
Driver={MySQL ODBC 5.2 ANSI Drive};Server=10.10.10.10;Port=3306;Database=testdb;User=ysoftman;Password=abcd1234

MS-SQL
Driver={SQL Server};Server=10.10.10.10,3306;DSN=dsn_test;Database=testdb;Uid=ysoftman;Pwd=abcd1234;


MySQL / Oracle 다음 시퀀스 값 가져오기

db 테이블에서 Oracle sequence 나 MySql auto_increment 속성으로 설정된 컬럼에서 다음 값을 파악해야 하는 경우가 있다.

[Oracle]
# 시퀀스 생성
create sequence id_seq start with 1 increment by 1 maxvalue 9999999999;
# 다음 시퀀스 파악
select nextval() from table_a;

nextval() 할 때마다 자동 증가된 값을 파악할 수 있다.
멀티쓰레드 환경에서 다수의 db 커넥션으로 수행해도 겹치지 않는 증가 값을 가져올 수 있다.

[MySQL]
# 테이블 생성시 컬럼 속성을 auto_increment 로 지정
create table table_a (
seq_id bigint(19) not null AUTO_INCREMENT, # (자동증가)
col1 int(9) default null,
col2 int(9) default null,
PRIMARY KEY (seq_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 최근에 inset 된 후 id 값 파악
# last_insert_id() 를 통해 가장 최근에 insert id 를 파악할 수 있다.
select last_insert_id();


하지만 mysql 의 경우 db 커넥션 마다 독립된 id 값을 별도로 관리하기 때문에
다수의 db 커넥션에서 last_insert_id() 시 같은 값을 가질 수 있다.
예를 들면...
A, B 가 각각 다른 db 커넥션을 가지고 같은 테이블에 insert 를 한다고 했을때
A가 insert 후 last_insert_id() 하면 1
B가 insert 후 last_insert_id() 하면 1
즉 세션마다 유니크한 값을 유지할 수는 있지만 모든 세션에서 유닉크한 값은 될 수 없다.

실제 테스트 해보니 커넥션마다 독립적으로 마지막으로 insert 한 id(auto increment)값을 파악할 수 있었다.
다음과 같은 순서로 쿼리했을때
커넥션1로 insert 3번
커넥션2로 insert 1번
커넥션1에서 select last_insert_id();  -> 3
커넥션2에서 select last_insert_id();  -> 1
와 같이 원하는 값을 얻을 수 있었다.


다음과 같은 다른 방법을 생각해 볼 수 있다.

# 자동 커밋을 안되게 하여 트랜잭션 처리를 가능하게 한다.
set autocommit=0;

# InnoDB 에서의 락 방법
# for update 는 쿼리(트랜잭션)를 실행한 세션을 제외한 모든 세션은 row 에 대한 접근 대기 상태가 된다. (for update 외에 select 는 가능한 lock in share mode 가 있다.)
# 쿼리가 종료되면 락은 풀린다.
# insert 하기전 미리 자동 증가 값을 파악할 수 있다.
select ifnull(max(seq_id)+1, 1) from table_a for update;

# insert 하면 자동증가 값은 위에서의 max(seq_id)+1 이 된다.
insert into tabe_a(col1, col2) values(1, 2);

SQL IDE/QueryBrowser

[SQL IDE/QueryBrowser]
SQL Developer http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html
MySQL WorkBench http://www.mysql.com/downloads/workbench/
SSMS(SQL Server Management Studio) http://www.microsoft.com/en-us/download/details.aspx?id=7593

ARM 계열 맥북 M1 등에서 mysql workbench 최신 버전(8.0.x)이 계속 크래시 되는 이슈가 있다.

대신 dbeaver 를 사용하자.
brew install --cask dbeaver-community

이름에 커서 위치시키고 f4 : table view
cmd+shift+r : open resource (.sql .erd등 파일 열때 유용)
cmd+enter : 쿼리 하나 실행
cmd+\ : 현재탭의 모든 쿼리 실행
ctrl+/ : 현재 라인 주석 토글
ctrl+shift+f : 쿼리 포맷팅
alt+up : 이전 쿼리 위치로 이동
alt+down : 다음 쿼리 위치로 이동
ctrl+shift+j : 라인 합치기
ctrl+shift+\ : 실행 결과 창 닫기
cmd+shift+x : to uppercase
cmd+shift+y : to lowercase
cmd+shift+e : editor 선택 팝업
cmd+s : editor 내용 저장, 레코드 결과 수정 적용
ctrl+r : 레코드 결과 수정 취소
ctrl+tab (customize) : next tab
ctrl+shift+tab (customize) : previous tab
ctrl+e (customize) : switch active panel (디폴트 ctrl+alt+t 는 rectangle 앱 단축키와 중복)

[터미널에서 사용하는 SQL IDE]

[harlequin]
설치
pip install harlequin harlequin-mysql

mysql 접속
harlequin -a mysql -h localhost -p 3306 -U root --password example --database dev --theme one-dark

설정 파일($XDG_CONFIG_HOME/harlequin/config.toml)을 만들어 두자.
default_profile = "ysoftman"
[profiles.ysoftman]
adapter = "mysql"
theme = "one-dark"
limit = 100000
host = "localhost"
port = "3306"
database = "test"
user = "user1"
password = "abc123"
connection_timeout = "10"

이제 할리퀸 실행하면 하면 위 설정으로 실행된다.
harlequin

sql query examples

-- show command 로 정보 확인
show databases;
show tables;
show variables;
show processlist;
show variables like 'log_output%';
show variables like '%timeout%';
show variables like 'event%';

-- slow 쿼리 로깅 활성화, 상태 확인
-- slow_query_log_file 위치의 파일을 확인하면 된다.
set global slow_query_log = 'on';
show global variables like 'slow_query_log%';

-- event 활성
show variables like 'event%';
set global event_scheduler = on;

-- event 생성
create event delete_history
on schedule every 1 day
comment '매일 히스토리 정리'
do
delete from history1 where created_at < (now() - interval 6 month);
delete from history2 where start_at < (now() - interval 6 month);

show events;
drop event delete_history;

-- db 선택
use ysoftman;

-- mysql 버전확인
select version();

-- create
create table `test_info` (
`id` bigint(20) unsigned not null auto_increment,
`age` int(11) default null,
`name` varchar(45) default null,
`nickname` varchar(45) default null,
`enable` tinyint(1) default 1,
`created_at` datetime default current_timestamp,
`updated_at` datetime default current_timestamp,
`deleted_at` datetime default current_timestamp,
`last_date` datetime default null,
primary key (`id`)
) engine=innodb default charset=utf8;

-- show create table
show create table test_info;

-- alter
alter table test_info default character set utf8mb4 default collate utf8mb4_bin;

-- delete
delete from test_info where name='ysoftamn';

-- update
update ysoftman.test_info set nickname = 'xelloss' where name = 'bill';
update ysoftman.test_info set nickname = 'xelloss' where name in ('bill', 'yoon', 'naruto');

-- select
select * from user;
select * from user limit 10;
select * from user where name like '%ysoftman%' or name like '%bill%';
select * from user order by id desc;
select * from user where created_at >= (now() - interval 1 month);
-- BETWEEN min AND max 으로 사용해야 한다.
select * from user where created_at between (now() - interval 1 month) and (now() - interval 1 day);

-- 3개의 테이블 left, right join
select
    svc1.name as svc1_name,
    svc1.description as svc1_desc,
    ifnull(svc2.aaa,'') as svc2_aaa,
    ifnull(svc3.aaa,'') as svc3_aaa,
from
    service1 svc1
right join service2 svc2 on
    svc1.service2_id = svc2.id
left join service3 svc3 on
    svc1.service3_id = svc3.id
where
    s.name = 'bill'
order by
    name asc;

-- major, minor 별 path 가장 높은 버전으로 조회
select
    *
from
    versions as t1
join (
    select
        version_major,
        version_minor,
        max(version_patch) as patch
    from
        versions
    where
        stable = 1
        and version_major >= 0
        and version_minor >= 1
    group by
        version_major,
        version_minor
) as t2 on
    t1.version_major = t2.version_major
    and t1.version_minor = t2.version_minor
    and t1.version_patch = t2.patch;

/*
mssql 저장 프로시져 테스트
*/
use [TestSP]
create proc SPQuery(
@a varchar(20),
@b varchar(20),
@c int,
@d float,
@e bigint,
@f int)
as
declare @idx int;
set @idx = 0;
while (@idx < 10)
begin
insert into mytable(col1, col2, col3, col4, col5, col6) 
values(@a, @b, @c, @d, @e, @f)
set @idx = @idx + 1
end

/*
저장 프로시져 실행
*/
exec SPQuery 'ysoftman', yoon, 123, 1.0, 12345, 123

#####

# mysql 접속해서 쿼리 실행하기
# -h host
# -u user
# -p passowrd (-p뒤에 공백없이 패스워드 명시)
# -N, --skip-column-names 결과 출력에서 컬럼명 제외
# -B, --batch 결과 출력시 dash(-) 표시 제외
# -e statement
# key같이 예약어가 있을 수 있어 ``로 감싸주는게 좋다.
mysql -h 127.0.0.1 -u ${mysql_user} -p${mysql_password}" mydb -NB -e 'select `key` from ysoftman;' 2> /dev/null

Linux Oracle libocci.so: undefined reference to 에러 해결 방법

리눅스에서 Oracle Call Interface (OCI) 를 라이브러를 링크하여 빌드할때
-locci 옵션만 사용할 경우 다음과 같은 링크 에러가 발생한다.
libocci.so: undefined reference to ....

[해결방법]
-lclntsh -lnnz11 -locci(또는 -lociei) 를 사용하도록 한다.

// 11 버전일때
Client Code Library (libclntsh.so.11.1) --> ln -s libclntsh.so.11.1 libclntsh.so 로 링크
Security Library (libnnz11.so)
OCCI Library (libocci.so.11.1)  --> ln -s libocci.so.11.1 libocci.so 로 링크
OCI Library (libociei.so)

(자세한 설명)
http://docs.oracle.com/cd/B28359_01/appdev.111/b28390/install.htm

Linux Oracle 11g 설치시 한글깨짐 현상 해결 방법

Oracle 11g 설치시  ./runinstaller 를 실행시켰을때 글자자 네모상자로 깨져 나올 경우
export LANG=C
export LC_ALL=C

를 실행후

./runinstaller

Linux odbc / sqlite mysql oracle 설치 및 환경 설정

// unixODBC 설치
sudo yum -y install glibc-devel.i686 unixODBC-devel.i686 glibc-devel.x86_64 unixODBC-devel.x86_64

// oracle odbc 드라이버 설치
(64bit일경우, 다운로드 : http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html)
sudo rpm -ivh oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
sudo rpm -ivh oracle-instantclient11.2-odbc-11.2.0.3.0-1.x86_64.rpm

//mysql odbc 드라이버 설치
sudo yum -y install mysql-connector-odbc mysql-devel

// sqlite 드라이버 설치
sudo yum -y install sqlite-*

// sqliteodbc-0.94 설치(gcc 4.1.2 이하에선 sqliteodbc-0.89 이하 버전설치)
./configure
make
sudo make install

// odbcinst.ini 및 odbc.ini 설정파일 위치 파악
odbcinst -j

// odbc driver 설정
// driver 를 찾을 수 없다는 실패 메시지가 발생하면 /usr/local/etc/odbcinst.ini 에 만들도록 한다.
sudo vi /etc/odbcinst.ini 또는 /usr/local/etc/odbcinst.ini
[SQLite]
Description=SQLite ODBC Driver
Driver=/usr/local/lib/libsqlite3odbc.so
Setup=/usr/local/lib/libsqlite3odbc.so
Threading=2

[MySQL]
Description     = ODBC for MySQL
Driver          = /usr/lib/libmyodbc3_r.so
Setup           = /usr/lib/libodbcmyS.so
Driver64        = /usr/lib64/libmyodbc3_r.so
Setup64         = /usr/lib64/libodbcmyS.so
FileUsage       = 1

[OracleODBC-11g]
Description = Oracle ODBC driver for Oracle 11g
Driver = /usr/lib/oracle/11.2/client64/lib/libsqora.so.11.1
FileUsage = 1
Driver Logging = 7

// DSN 설정하기
sudo vi /etc/odbc.ini 또는 /usr/local/etc/odbc.ini
[oracle]
Description=ODBC for oracle client 64
Driver=OracleODBC-11g

// odbc driver 파악
odbcinst -q -d

// odbc dsn 파악
odbcinst -q -s

// 참고 ORACLE 클라이언트 환경 설정(.bashrc 에 설정)
export ORACLE_SID=ysoftman_service_id
export TNS_ADMIN=/usr/lib/oracle/11.2/client64/
export PATH=/usr/lib/oracle/11.2/client64/bin:$PATH
export NLS_LANG="AMERICAN_AMERICA.UTF8"
export TWO_TASK=ysoftman_service_id

// isql 로 접속해보기
isql oracle userid password

// sqlplus 로 접속해보기(TWO_TASK로 접속대상을 설정해서 호스트는 생략)
sqlplus userid/password

Windows 7 Oracle 10g Client 설치시 운영체제 요구 사항 오류 해결 방법

윈도우 7에서 Oracle 10g 를 설치 할때 아래와 같이 운영체제를 알 수 없어 설치를 할수 없게 된다.


[해결방법]
다음의 2개 파일에 아래와 같이 윈도우 7 버전 정보를 추가한다.
Disk1\stage\prereq\client\refhost.xml
Disk1\stage\prereq\client_prereqs\client\refhost.xml

... 생략 ...

<CERTIFIED_SYSTEMS>
<OPERATING_SYSTEM>
<!--Microsoft Windows 2000-->
<VERSION VALUE="5.0"/>
<SERVICE_PACK VALUE="1"/>
</OPERATING_SYSTEM>
<OPERATING_SYSTEM>
<!--Microsoft Windows XP-->
<VERSION VALUE="5.1"/>
<SERVICE_PACK VALUE="1"/>
</OPERATING_SYSTEM>
<OPERATING_SYSTEM>
<!--Microsoft Windows 2003-->
<VERSION VALUE="5.2"/>
</OPERATING_SYSTEM>
<!--Microsoft Windows Vista-->
<OPERATING_SYSTEM>
<VERSION VALUE="6.0"/>
</OPERATING_SYSTEM>
<!--Microsoft Windows 7-->
<OPERATING_SYSTEM>
<VERSION VALUE="6.1"/>
</OPERATING_SYSTEM>
</CERTIFIED_SYSTEMS>

MSSQL 계정 암호 변경하기

MSSQL 에서 sa 나 기타 로그인 아이디에 대한 패스워드를 잊어 버렸다면 아래와 같이 재설정 할 수 있다.
cmd 콘솔에서 sqlcmd 을 실행한다. (참고로 :help 하면 도움말이 표시된다.)
1> alter login ysoftman with password="abc123";
2> go
3> exit