IT 인터넷/Node.js

SELECT ... FOR UPDATE :: MySQL

Banjubu 2023. 6. 19. 19:12
반응형

 

값이 비었을 때 새로운 값을 넣는 API가 있다고 가정해요.

const [rows] = await db.query('SELECT * FROM temp')
if ((rows as ITemp[]).length < 1) {
  await db.query(`INSERT INTO file (id) VALUES ('1111')`)
}

 

동시에 세 번 호출하면 모든 호출은 동시에 SELECT를 실행하기 때문에 다 값이 없다고 판단하고 1111을 기록해요.

$ autocannon -c 3 -a 3 http://localhost:3100/user/test

 

 

이를 방지하기 위해 SELECT 문 뒤에 FOR UPDATE를 붙여요.

const [rows] = await db.query('SELECT * FROM temp FOR UPDATE')
if ((rows as ITemp[]).length < 1) {
  await db.query(`INSERT INTO file (id) VALUES ('1111')`)
}

 

이제 여러 번 호출해도 한 번만 기록되요.

 

다만, 아래와 같은 단점도 있으니 주의해야 해요. (by Bard)

- 성능 저하: SELECT FOR UPDATE로 락된 데이터는 다른 트랜잭션이 해당 데이터를 수정할 수 없기 때문에 성능이 저하될 수 있습니다.
- 데드락: 두 트랜잭션이 서로 다른 데이터를 락하여 서로를 기다리게 되는 경우 데드락이 발생할 수 있습니다. 데드락이 발생하면 두 트랜잭션 모두 실행이 중단됩니다.
- 데이터 무결성 손상: SELECT FOR UPDATE로 락된 데이터를 수정하면 데이터 무결성이 손상될 수 있습니다.

 

 

 

반응형
LIST