개발자의 길/Database 9

[MySQL] 스토어드 프로시저

개발을 하다 보면 쿼리문 작성에 시간을 많이 쏟게 되고, ORM 이던 Raw query 문이던 쿼리 작성을 위한 코드를 프로젝트에 많이 넣게 되는데, 이런 쿼리 레벨에서의 로직을 DB 에 직접 넣을 수 가 있다. MySQL 에서 '스토어드 프로시저' 라는 기능으로 제공되고 있다. 간단히 말하면 데이터베이스 내에 하나의 함수를 작성한다고 보면 된다. 스토어드 프로시저를 쓰면 아래와 같은 장점이 있다. 성능 향상: 스토어드 프로시저는 데이터베이스 서버에서 실행되므로 네트워크 지연을 줄일 수 있고, 데이터 처리를 최적화할 수 있다. 재사용성: 스토어드 프로시저는 여러 번 호출할 수 있으며, 코드 중복을 방지하고 관리가 쉽다. 보안 강화: 애플리케이션에서 직접 SQL 쿼리를 작성하는 대신 스토어드 프로시저를 호..

[MySQL] MySQL 의 Isolation level ( 격리 레벨 )

여타 RDBMS 와 같이 MySQL 역시 데이터의 정합성을 위해서 데이터를 잠그거나, transaction 단위로 작업을 관리하고, 각 트랜잭션이 수행한 작업들을 별도 로그에 저장해서 언제든 롤백할 수 있도록 관리하고 있다. 여기서 격리 레벨은 이 데이터 정합성을 지키기 위해 얼마나 엄격히 트랜잭션간의 작업을 격리시키는지를 의미하는데, 다음과 같이 4 단계의 격리 레벨이 있다. READ UNCOMMITTED 가장 낮은 격리 수준으로, 다른 트랜잭션에서 커밋되지 않은 변경 내용을 볼 수 있으며, 이로 인해 'Dirty Read'가 발생할 수 있다. READ COMMITTED 커밋된 데이터만 읽을수 있게 되어서 'Dirty Read'는 방지하지만, 'Non-Repeatable Read' 문제는 여전히 발생한..

[MYSQL] OUTER JOIN 과 INNER JOIN

MYSQL 에서 꽤나 자주 쓰이는 join 에 대해 설명하고자 한다. join 은 두 테이블의 column 을 비교하여 일치하는 row 들을 조합하는 것이다. Inner Join Inner Join은 두 테이블 간의 교집합을 찾는 SQL 조인 방식이다. 이 방식은 두 테이블에서 일치하는 데이터만 반환한다. 예를 들어, '고객' 테이블과 '주문' 테이블을 Inner Join 하면, 주문 기록이 있는 고객 정보만을 가져온다. 사용 예 SELECT * FROM 고객 INNER JOIN 주문 ON 고객.고객ID = 주문.고객ID; 이 쿼리는 '고객'과 '주문' 테이블에서 고객 ID가 일치하는 레코드만을 선택한다. Outer Join Outer Join은 두 테이블의 합집합을 반환한다. 이 방식은 일치하는 데이터..

[SQLite3][C++] database is malformed - DB 에 손상이 갔을 때.

여느때와 같이 bug ticket 이 들어왔나 보고 있던 중에, 내 모듈이 SQLite DB 에 저장한 데이터를 읽을 수 없었다는 이슈가 있었다. log 상으로는 어떠한 문제점도 보이지 않아서 설치된 DB 를 받아서 분석을 해 보았더니, 읽을 수 없었던 PK 를 SELECT 하려고 시도하니 database is malformed 라는 문구가 뜬 적이 있었다. 해당 로그에 대한 자료를 찾아보니 pragma integrity_check 라는 PRAGMA 를 이용해서 DB 가 손상되었는지 확인 할 수 있었지만, 손상되었다는 정보만 얻고 별 소득이 없었다. 결국에 해결해야 되는 것은 내가 구현한 모듈에서 DB 를 손상시킬 수 있는 동작을 하고 있었다는 점이기 때문이다. 우선 모듈은 DB 에 Read/Write ..

[SQLite3][C++] SQLite3 에서 record 를 지워도 DB 용량이 줄어들지 않는 이유는? - page, vacuum, rbu vacuum.

SQLite3 에서 아래와 같이 DELETE query 를 실행하면 record 를 지울 수 있다 DELETE FROM [table_name] WHERE [column_value]=? WHERE 문을 제거하면 전체 테이블이 모두 지워지는데, DELETE Query 를 이용해서 record 는 모두 삭제가 되어도 DB 용량은 그대로인 것을 볼 수가 있을 것이다. 이는 SQLite3 가 reocrd 를 삭제해도 디스크로부터 할당받은 데이터 공간을 바로 버려버리는 것이 아니라, 이후에 새로운 record 가 Insert 되었을 때 재활용하기 위해 page 단위로 빈 공간이라는 정보를 유지하고 있기 때문이다. Vacuum 그러면 DB Size 를 줄이기 위해서는 어떻게 해야 하는가? 간단하게도 VACUUM 이라..

[SQLite3][C++] Sqlite3 의 journal file 에 대해

SQLite 의 Journal file SQLite 에서는 갑작스러운 power failure 등으로 인한 쓰기 작업이 중단되었을 경우 DB 손상을 막기 위해 Rollback Journal 이라는 기법을 사용한다. DB 에 write 작업이 발생하게 되면, rollback journal 이라는 곳에 데이터가 write 로 인해 변경되기 전으로 돌아갈 수 있도록 하는 정보들을 기록하게 된다. 데이터 write 및 commit 이 종료되면 journal file 을 삭제하게 되며, 쓰기작업 도중에 종료될 경우 삭제하지 않은 journal file 이 남아있는 상태로 남아있게 된다. rollback journal 을 이용해 무결성 복원을 해야하는 경우 이 journal 을 hot journal 이라고 부르는데..

[SQLite3][C++] SQLite 의 file lock 매커니즘

ACID 와 SQLite3 SQLite3 는 Database 의 ACID 를 준수하기 위한 하나의 방법으로 File Locking Mechanism 을 사용한다. 잠시 ACID 에 복습해 보자면 아래와 같다. Atomicity 원자성 : 하나의 논리적 실행단위인 트랜잭션이 도중이 중단되지 않고 끝까지 실행되어야 함 Consistency 일관성 : 트랜잭션 실행이 종료된다면 언제나 일관성 있는 상태의 Database 가 되어야 한다. Isolation 독립성 : 트랜잭션 수행 중에는 다른 어떠한 트랜잭션이 도중에 끼어들거나 트랜잭션의 중간 작업내용을 볼 수 없음을 의미한다. Durability 지속성 : 한번 트랜잭션이 수행 되었다면 그 결과는 시스템 장애나 전원 종료 등이 발생하더라도 영구히 남아야 함을..

[SQLite3][C++] sqlite3_busy_timeout

지난 포스팅에 이어, SQLite3 database 가 locked 상태인 경우에 일정 시간 대기를 하도록 설정이 가능한 sqlite3_busy_timeout 함수를 살펴보고자 한다. 해당 함수에 대한 문서는 아래 주소를 참고 바란다. https://www.sqlite.org/c3ref/busy_timeout.html sqlite3_step 을 통해 DB 에 접근을 하는 동작을 수행할 때 만약에 DB 가 Write 접근 - Read lock 이나 Read/Write 접근 - Write lock 인 상태에는 SQLITE_BUSY 를 즉시 리턴하게 된다. 여러 쓰레드/프로세스에서 해당 데이터베이스에 접근하는게 일반적인 상황이라면 즉시 접근실패를 하고 종료하는 것 보다 lock 을 놓을 때 까지 대기하는것이 ..

[SQLite3][C++] database is locked 에러가 나올 때 ?

database is locked 에러가 나올 때 SQLite 개발을 하다 보면 저런 에러메시지를 만나거나 에러코드 SQLITE_BUSY (5) 를 반환받아서 DB 에 대한 읽기/쓰기 가 불가능한 경우를 본 적이 있을 것이다. 해당 에러코드가 리턴되는 경우는 DB 에 Write 작업을 하는 도중, Read/Write 를 하고자 접근을 한 경우이다. SQLite 는 기본적으로 Atomicity (원자성) 을 지키기 위해서 DB 에 write 작업이 발생을 할 경우 File 단위로 lock 을 걸어 버려서, 같은 Database 의 다른 table 에 접근한다 하더라도 lock 이 걸린 상태에서는 읽기/쓰기가 불가능하다. 혹시나 SQLite3 Lib 을 이용한 프로그램에서 저런 문제가 나온다면, 읽기/쓰기가..

반응형