# Active Record와 mini\_sql을 함께 사용하면 예상치 못한 동작이 발생합니다

**URL:** <https://meta.discourse.org/t/mixing-active-record-mini-sql-leads-to-unexpected-behavior/176504>\
**Category:** Bug\
**Created:** [1월 19, 2021, 2:18오전 UTC](https://meta.discourse.org/t/mixing-active-record-mini-sql-leads-to-unexpected-behavior/176504 "2021-01-19T02:18:24Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![concerto](https://avatars.discourse-cdn.com/v4/letter/c/dec6dc/32.png) [@concerto](https://meta.discourse.org/u/concerto)\
**Post date:** [1월 19, 2021, 2:18오전 UTC](https://meta.discourse.org/t/mixing-active-record-mini-sql-leads-to-unexpected-behavior/176504/1 "2021-01-19T02:18:24Z")

</div>

일부 SQL 로그를 검토하던 중, Active Record와 [mini\_sql](https://github.com/discourse/mini_sql)의 혼용 사용으로 인해 일부 쿼리가 코드의 의도와 일치하지 않는 것을 발견했습니다.

일부 reviewables를 업데이트할 때, 가능한 레이스 컨디션(race condition)을 방지하기 위해 트랜잭션 내에서 version을 증가시킵니다(아래 코드 스니펫 참조). 증가 연산이 트랜잭션의 일부인 것처럼 보이지만, 실제로는 그렇지 않습니다.

> <https://github.com/discourse/discourse/blob/d0ef952af296f4fe00c8be56f4e8cede8095d2d6/app/models/reviewable.rb#L348-L352>

여기서 `Reviewable.transaction`은 Active Record의 기능인 반면, `increment_version!`은 mini\_sql을 사용합니다:

> <https://github.com/discourse/discourse/blob/d0ef952af296f4fe00c8be56f4e8cede8095d2d6/app/models/reviewable.rb#L628-L650>

Active Record는 mini\_sql이 수행하는 작업을 인지하지 못합니다. Active Record는 어떤 지연(lazy) 기능을 사용하여 트랜잭션 내부의 첫 번째 쿼리가 발행되기 직전에 `BEGIN`을 발행하는 것 같습니다. 따라서 version이 먼저 증가되고, Active Record의 첫 번째 쿼리가 발행되기 직전에 트랜잭션이 시작됩니다. 그 결과 다음과 같은 상황이 발생합니다:

```sql
UPDATE reviewables SET version = version + 1 WHERE version=version AND id = reviewable.id RETURNING version;
BEGIN;
...

```

version 증가가 트랜잭션 외부에서 수행되면, 낙관적 잠금(optimistic locking)이 제공하는 일부 보장이 달성되지 않습니다. 증가 연산이 트랜잭션과 원자적(atomic)으로 처리되지 않기 때문입니다.

---

<div class="post-metadata">

**Author:** ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)\
**Post date:** [1월 31, 2021, 11:24오후 UTC](https://meta.discourse.org/t/mixing-active-record-mini-sql-leads-to-unexpected-behavior/176504/2 "2021-01-31T23:24:57Z")

</div>

흥미롭네요. mini sql을 통해 AR에 정보를 전달하는 방식을 가르쳐야 할 것 같습니다. 분명히 수정할 가치가 있습니다.
