따라서 깊게 고민 하지 않고, “아 이런 내용이 있구나” 정도로만 간단히 이해하고 넘어가셔도 좋습니다. 😉
-- 트랜잭션을 시작합니다.
**START TRANSACTION;**
-- 성공시 작업 내역을 DB에 반영합니다.
**COMMIT;**
-- 실패시 START TRANSACTION이 실행되기 전 상태로 작업 내역을 취소합니다.
**ROLLBACK;** 트랜잭션을 사용하는 문법을 확인해보았으니,[코드스니펫] MySQL의 트랜잭션 예시코드
```sql
-- SPARTA 테이블을 생성합니다.
CREATE TABLE IF NOT EXISTS SPARTA
(
spartaId INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
spartaName VARCHAR(255) NOT NULL,
spartaAddress VARCHAR(255) NOT NULL
);
-- 1번째 트랜잭션을 실행합니다.
START TRANSACTION;
-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA1', 'SEOUL'),
('SPARTA2', 'BUSAN'),
('SPARTA3', 'DAEGU');
-- 1번째 트랜잭션을 DB에 적용합니다.
COMMIT;
-- 2번째 트랜잭션을 실행합니다.
START TRANSACTION;
-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA4', 'SEOUL'),
('SPARTA5', 'BUSAN'),
('SPARTA6', 'DAEGU');
-- 2번째 트랜잭션을 롤백합니다.
ROLLBACK;
-- 테이블의 상태를 확인합니다.
SELECT * FROM SPARTA;
```

예시 코드를 실행할 경우, 2번째 트랜잭션에서 수행하는 INSERT INTO가 ROLLBACK되었기 때문에 실제 SPARTA 테이블은 6개가 아닌, 3개의 데이터만 삽입되어 있는 상태로 존재하게 됩니다.
**READ 전용 락**이라고 불리기도 하며, 해당 락을 사용하는 트랜잭션이 모든 작업을 수행하였다면 공유 락은 해제됩니다.# 트랜잭션을 시작합니다.
START TRANSACTION;
# SPARTA 테이블을 조회할 때, 해당 데이터들에 공유 락을 설정합니다.
SELECT * FROM SPARTA LOCK IN SHARE MODE;**WRITE 전용 락이라고 불리며, 트랜잭션이 해당하는 데이터를 점유한 후 다른 트랜잭션이 해당 데이터에 접근 할 수 없도록** 만듭니다.# 트랜잭션을 시작합니다.
START TRANSACTION;
# SPARTA 테이블을 조회할 때, 해당 데이터들에 배타 락을 설정합니다.
SELECT * FROM SPARTA FOR UPDATE;글로벌 락(Global Locks) | 데이터베이스 락(Database Locks)
# 글로벌 락을 획득합니다.
# MySQL 서버에 존재하는 모든 테이블에 락을 겁니다.
FLUSH TABLES WITH READ LOCK;# SPARTA 테이블에 테이블 락을 설정합니다.
LOCK TABLES SPARTA READ;# sparta_name 문자열을 획득합니다.
# 만약, 10초 동안 획득 하지 못한다면, NULL을 반환합니다.
SELECT GET_LOCK('sparta_name', 10);메타데이터 락(Metadata Locks)
- 다른 사용자가 작업중인 테이블의 동일한 행 및 동일한 데이터베이스의 객체를 동시에 수정하지 못하도록 합니다.
- 예시 SQL
```sql
# 테이블 구조를 변경할 때, MySQL은 내부적으로 메타데이터 락을 설정합니다.
ALTER TABLE SPARTA ADD COLUMN Age Int;
```
📌 락은 다양한 **락킹 수준(Locking Level)**을 가지고 있는데, 잘못된 락 설정을 하게 될 경우 여러분들은 모든 API가 동작하지 않는 **교착 상태(Dead Lock)**가 발생하게 되어, 프로그램이 멈춰버리는 문제가 발생하게 될 수 있습니다.
❓ 교착 상태(Dead Lock)를 해결하기 위해선 어떻게 구성해야할까요?
💡 **교착 상태(Dead Lock)**는 여러 테이블에 **락(Lock)**을 적용하여, 다른 작업이 처리되지 못하게 점유하고 있는 작업이 있을 때, 다른 작업을 끝나는 것을 무한정 기다리는것을 나타냅니다.
](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/88e5dd69-0c9a-4d1f-a027-57830e276d0f/deadlock.png)
출처: [sqlhack.com](https://www.sqlshack.com/understanding-the-deadlock-definition-in-sql-server/)
💡 **교착 상태**의 경우 아래와 같은 **2개의 트랜잭션이 동시에 실행**된다고 가정해보겠습니다.
1️⃣ A→ B 테이블을 순차적으로 사용하는 트랜잭션
2️⃣ B→ A 테이블을 순차적으로 사용하는 트랜잭션
가장 먼저 1️⃣ 은 처음 **A 테이블**을 점유하기 위해 **락**을 걸어놓을 것 입니다. 그리고 동시에 2️⃣ 또한 **B 테이블**을 점유하기 위해 **락**을 걸어놓을 것 입니다.
그러면 1️⃣ 은 **B 테이블**의 락이 풀리기를 기다리는 상태가 발생하게 될 것이고, 2️⃣ 또한 **A 테이블**의 락이 풀리기를 기다리는 상태가 발생하게 될 것 입니다. 이처럼 리소스를 접근하려고 할 때, 서로가 서로의 리소스를 점유하고 있을 때 발생하는 것을 **교착 상태(Dead Lock)**이라고 부릅니다.
해당하는 상황을 해결하기 위해 여러분들은 트랜잭션에서 사용하는 **락(Lock)**의 수준을 명확하게 이해하고, 적재적소에 필요한 락의 수준을 설정하여 트랜잭션을 구성해야합니다.
💡 트랜잭션의 격리 수준 (Isolation Level)은 여러 트랜잭션이 동시에 처리될 때 다른 트랜잭션에서 변경 및 조회하는 데이터를 읽을 수 있도록 허용하거나 거부하는 것을 결정하기 위해 사용하는 것 입니다.
→ 여기서, 중요한 점은 **‘데이터의 일관성’**과 **‘동시성 처리 성능’** 사이에서 **균형**을 잡는 것입니다.
트랜잭션의 격리 수준은 대표적으로 4가지로 나타냅니다.
`**READ UNCOMMITTED**`
- **커밋 되지 않은 읽기(Uncommitted Read)**를 허용하는 격리 수준입니다.
- 가장 낮은 수준의 격리수준이며, 락을 걸지 않아 동시성이 높지만 일관성이 쉽게 깨질 수 있습니다.
`**READ COMMITTED**`
- **커밋 된 읽기(Committed Read)**만을 허용하고, `SELECT` 문을 실행할 때 **공유락**을 겁니다.
- 다른 트랜잭션이 데이터를 **수정하고 있는 중**에는 **데이터를 읽을 수 없어** 커밋되지 않은 읽기현상이 발생하지 않습니다.
**`REPEATABLE READ`**
- 읽기를 마치더라도 **공유락**을 **풀지 않으며**, 트랜잭션이 **완전히 종료될 때 까지 락을 유지**합니다.
- 공유락이 걸린 상태에서 데이터를 수정하는 것은 불가능하지만, 데이터를 삽입하는 것이 가능해집니다. 그로인해 **팬텀 읽기**가 발생할 수 있는 문제점이 있습니다.
`**SERIALIZABLE**`
- 데이터를 읽는 동안 다른 트랜잭션이 해당 데이터를 읽거나 삽입할 수 없고, 새로운 데이터를 추가하는 것 또한 불가능합니다.
- **가장 높은 수준의 격리 수준**이므로, 동시성이 떨어지는 문제점이 존재합니다.
- **❓ 커밋되지 않은 읽기(Uncommitted Read)는 무엇일까요?**
💡 **커밋되지 않은 읽기(Uncommitted Read)**는 다른 트랜잭션에 의해 작업중인 데이터를 읽게 되는 것을 나타냅니다. 만약 커밋되지 않은 읽기가 발생할 경우, **의도치 않은 데이터를 참조**하게 되어 **데이터의 일관성이 깨지게 되는 상황**이 발생하게됩니다.
- **❓ 팬텀 읽기(Phantom Read)란 무엇일까요?**
💡 트랜잭션을 수행하던 중 **다른 트랜잭션**에 의해 **삭제된 데이터**를 **팬텀행(Phantom Rows)**이라고 합니다. 여기서, **팬텀행**에 해당하는 데이터를 읽는 것을 **팬텀 읽기(Phantom Read)**라고 부릅니다.