forked from JAVACAFE-STUDY/2024-real-mysql-1
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
127 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
## 트랜잭션 | ||
|
||
트랜잭션은 논리적인 작업 셋 자체가 100% 적용되거나 아무것도 적용되지 않아야 함을 보장해주는 것이다. | ||
|
||
AUTO-COMMIT 모드에서 테스트를 하면 MyISAM은 데이터가 저장된 이후 오류가 발생하지만, InnoDB의 경우 쿼리 중 일부라도 오류가 발생하면 INSERT 문장을 실행하기 전으로 복구한다. | ||
|
||
### 최적의 트랜잭션 설계 | ||
|
||
- 데이터베이스 커넥션을 가지고 있는 범위와 트랜잭션이 활성화되어 있는 범위를 최소화해야 한다 | ||
- 네트워크 작업이 있는 경우, 반드시 트랜잭션에서 배제해야 한다 | ||
- DBMS 서버 높은 부하 상태에 빠지거나 위험산 상태에 빠지는 경우가 빈번하다 | ||
|
||
## MySQL 엔진의 잠금 | ||
|
||
MySQL에서 사용되는 잠금은 크게 스토리지 엔진 레벨과 MySQL 엔진 레벨로 나눌 수 있다. MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미치지만, 스토리지 엔진 레벨의 잠금은 스토리지 엔진 간에 상호 영향을 미치지 않는다. | ||
|
||
### 글로벌 락 | ||
|
||
- FLUSH TABLES WITH READ LOCK 명령으로 획득 가능 | ||
- MySQL에서 제공하는 잠금 중 범위가 가장 큼 | ||
- 한 세션에서 글로벌 락 획득 → 글로벌 락이 해제될 때까지 대기 | ||
- 영향을 미치는 범위는 서버 전체 | ||
- 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향을 미침 | ||
|
||
### 테이블 락 | ||
|
||
- 개별 테이블 단위로 설정되는 잠금 | ||
- LOCK TABLES table_name READ | WRITE 명령으로 특정 테이블의 락 획득 가능 | ||
- UNLOCK TABLES 명령으로 반납 가능 | ||
- 묵시적 테이블 락이 발생하는 경우 | ||
- MyISAM, MEMORY 테이블에 데이터 변경 쿼리를 실행할 때 | ||
- InnoDB 테이블에 스키마를 변경하는 DDL 쿼리를 실행할 때 | ||
|
||
### 네임드 락 | ||
|
||
- GET_LOCK() 함수를 이용해 임의의 문자열에 대한 잠금을 설정 | ||
- 자주 사용되지 않음 | ||
- 유용하게 사용 가능한 경우 | ||
- 여러 클라이언트가 상호 동기화를 처리해야 할 때 | ||
- 많은 레코드에 대해 복잡한 요건으로 레코드를 변경해야 할 때 | ||
|
||
### 메타데이터 락 | ||
|
||
- 데이터베이스 객체의 이름이나 구조를 변경하는 경우 자동으로 획득하는 잠금 | ||
- RENAME TABLE 명령의 경우, 원본 이름과 변경될 이름 모두 한꺼번에 잠금을 설정함 | ||
- 2개로 나눠 실행하면 아주 짧은 순간이지만 테이블이 존재하지 않는 순간이 생겨 오류가 발생함 | ||
- 테이블의 구조를 변경해야 하는 경우 | ||
- 새로운 구조의 테이블 생성 → 최근 데이터까지는 id 값을 범위 별로 나눠서 여러 개의 스레드로 빠르게 복사 | ||
- 나머지 데이터를 복사할 때 트랜잭션과 테이블 잠금, 그리고 RENAME TABLE 명령으로 응용 프로그램의 중단 없이 실행할 수 있음 | ||
|
||
## InnoDB 스토리지 엔진 잠금 | ||
|
||
스토리지 엔진은 MySQL에서 제공하는 잠금과 별개로, 스토리지 엔진 내부에서 레코드 기반의 잠금 방식을 탑재하고 있다. 때문에 MyISAM보다 훨씬 뛰어난 동시성 처리를 제공한다. | ||
|
||
### InnoDB 스토리지 엔진의 잠금 | ||
|
||
- InnoDB 스토리지 엔진은 레코드 기반의 잠금 기능을 제공 | ||
- 레코드와 레코드 사이의 간격을 잠그는 갭 락 존재 | ||
|
||
### 레코드 락 | ||
|
||
- 레코드 자체만을 잠그는 것 | ||
- InnoDB 스토리지 엔진은 레코드 자체가 아닌 인덱스의 레코드를 잠금 | ||
- 인덱스가 하나도 없는 테이블 → 내부적으로 자동 생성된 클러스터드 인덱스를 이용해 잠금을 설정 | ||
- 프라이머리 키 또는 유니크 인덱스에 의한 변경 작업 → 레코드 자체에만 락을 검 | ||
- 보조 인잭스를 이용한 변경 작업 → 넥스트 키 락 또는 갭 락을 사용 | ||
|
||
### 갭 락 | ||
|
||
- 레코드 사이의 간격만을 잠그는 것 | ||
- 레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어 | ||
- 넥스트 키 락의 일부로 자주 사용됨 | ||
|
||
### 넥스트 키 락 | ||
|
||
- 레코드 락과 갭 락을 합쳐 놓은 형태의 잠금 | ||
|
||
### 자동 증가 락 | ||
|
||
- AUTO_INCREMENT 컬럼이 사용된 테이블에서 사용하는 테이블 수준의 잠금 | ||
- 동시에 여러 레코드가 INSERT 되는 경우, 저장되는 레코드가 중복되지 않고 순서대로 증가하는 일련번호 값을 가지기 위해 사용함 | ||
- 자동 증가 값이 한 번 증가하면 절대 줄어들지 않음 | ||
|
||
### 인덱스와 잠금 | ||
|
||
- InnoDB의 잠금은 인덱스를 잠그는 방식으로 처리됨 | ||
- 변경해야 할 레코드를 찾기 위해 검색한 인덱스의 레코드에 모두 락을 걸어야 함 | ||
- 테이블에 인덱스가 없다면 테이블을 풀 스캔하면서 UPDATE 작업을 함 | ||
- 이때, 테이블에 있는 모든 레코드를 잠그게 됨 | ||
|
||
MySQL의 InnoDB에서 인덱스 설계가 중요한 이유 | ||
|
||
### 레코드 수준의 잠금 확인 및 해제 | ||
|
||
- 테이블 잠금은 잠금의 대상이 테이블 자체 → 문제의 원인이 쉽게 발견되고 해결될 수 있음 | ||
- 레코드 수준의 잠금은 테이블의 레코드 각각에 잠금 → 해당 레코드가 자주 사용되지 않는다면 오랜 시간 잠겨진 상태로 남아있어도 잘 발견되지 않음 | ||
- 강제로 잠금을 해제하려면 KILL 명령어를 통해 MySQL 서버의 프로세스를 강제 종료하면 됨 | ||
|
||
## MySQL의 격리 수준 | ||
|
||
트랜잭션의 격리 수준은 여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지를 결정하는 것이다. 격리 수준이 높을수록 데이터의 격리 정도가 높아지고 동시 처리 성능도 떨어진다. | ||
|
||
### READ UNCOMMITTED | ||
|
||
- 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다 | ||
- Drity read | ||
- 트랜잭션에서 처리한 적업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 현상 | ||
|
||
### READ COMMITTED | ||
|
||
- 오라클 DBMS의 기본 격리수준 | ||
- Drity read 현상은 발생하지 않음 | ||
- COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있기 때문 | ||
- 하나의 트랜잭션 내에서 똑같은 SELECT 쿼리를 실행했을 때 항상 같은 결과를 가져오지 못하는 문제가 있음 | ||
|
||
### REPEATABLE READ | ||
|
||
- MySQL InnoDB 스토리지 엔진 기본 격리수준 | ||
- MVCC를 위해 언두 영역에 백업된 데이터를 이용해 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장함 | ||
- Phantom read | ||
- SELECT FOR UPDATE 쿼리를 여러 번 수행하면 결과라 다름 | ||
- 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다 안보였다 하는 현상 | ||
|
||
### SERIALIZABLE | ||
|
||
- 가장 단순하면서 가장 엄격한 격리수준 | ||
- 동시 처리 성능도 다른 트랜잭션 격리 수준보다 떨어짐 |