<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Mysql on Gukin Han</title>
    <link>https://gukin.dev/tags/mysql/</link>
    <description>Recent content in Mysql on Gukin Han</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Sat, 13 Dec 2025 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://gukin.dev/tags/mysql/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>상관 서브쿼리로 인한 읽기 병목 개선</title>
      <link>https://gukin.dev/posts/correlated-subquery-read-bottleneck/</link>
      <pubDate>Sat, 13 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/correlated-subquery-read-bottleneck/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;문제
&lt;ul&gt;
&lt;li&gt;운영 환경에서 조회 API 응답 지연(1초 이상) 이슈 발생&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;상관 서브쿼리로 인한 N+1 패턴&lt;/strong&gt;이 DB 레벨에서 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;과정
&lt;ul&gt;
&lt;li&gt;실행 계획 분석을 통해 Nested Loop 반복 실행과 &lt;strong&gt;옵티마이저 통계 오류&lt;/strong&gt;를 확인&lt;/li&gt;
&lt;li&gt;상관 서브쿼리를 &lt;strong&gt;CTE + Hash Join&lt;/strong&gt; 구조로 리팩토링&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;성과
&lt;ul&gt;
&lt;li&gt;서브쿼리 실행 &lt;strong&gt;92회에서 1회로 감소&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;총 실행 비용 &lt;strong&gt;246.0에서 40.6로 감소&lt;/strong&gt; (약 83% 개선, 6배 성능 향상)&lt;/li&gt;
&lt;li&gt;운영 데이터 기준으로 실행 계획 변화와 성능 개선을 수치로 검증&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;문제-배경&#34;&gt;문제 배경&lt;/h2&gt;
&lt;p&gt;운영 중인 서비스에서 특정 테넌트 기준 조회 API의 응답지연이 보고되었다. 슬로우 쿼리 분석 결과, 직원을 그룹화하는 테이블의 조회 쿼리 내부에 상관 서브쿼리(Correleated Subquery)가 포함되어있었다. 그 영향으로 메인 쿼리 결과 행 수만큼 서브쿼리가 반복 실행되는 문제가 발생했다.&lt;/p&gt;</description>
    </item>
    <item>
      <title>정규화부터 캐싱까지 - 상품 목록 페이지네이션 최적화 과정</title>
      <link>https://gukin.dev/posts/read-heavy-pagination-optimization/</link>
      <pubDate>Fri, 15 Aug 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/read-heavy-pagination-optimization/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;정규화 쿼리(집계 + 정렬)&lt;/strong&gt; → 풀스캔 + filesort로 &lt;strong&gt;~17초&lt;/strong&gt; 소요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;역정규화 + 정렬 포함 인덱스&lt;/strong&gt; → &lt;strong&gt;~227ms&lt;/strong&gt; (약 76배 향상).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OFFSET 페이지네이션&lt;/strong&gt; → 인덱스 순차 스캔 시작 → 임계점에서 Table Scan + Filesort로 전환 → 이후 응답시간 급등.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;전환 전 일정한 속도&lt;/strong&gt;는 InnoDB 버퍼 풀/캐시 히트율 덕분.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyset(Seek) 페이지네이션&lt;/strong&gt; → 깊은 페이지에서도 일정 성능 (421ms → 31ms, 92.6% 단축).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;인덱스 설계&lt;/strong&gt;는 핫 트래픽 패턴(브랜드 + 인기순/최신순/최저가순)에 맞춘 3개의 복합 인덱스 유지가 가성비 최적.
&lt;ul&gt;
&lt;li&gt;설계 원칙: 필터 선두 → 정렬키 → tie-breaker(id)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;캐시(Cache-Aside)&lt;/strong&gt; 적용 시 200RPS에서도 DB I/O 부하 없이 ms 단위 응답 가능.
&lt;ul&gt;
&lt;li&gt;단, TTL·Evict 정책·실시간성 요구사항·정합성 유지·스탬피드 방지 등 고려 필수.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결론: &lt;strong&gt;정규화/역정규화 → 인덱스 설계 → 페이지네이션 전략 → 캐싱&lt;/strong&gt;이 단계적으로 맞물려 성능을 좌우함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;문제-정의와-가설&#34;&gt;문제 정의와 가설&lt;/h2&gt;
&lt;p&gt;웹 서비스에서는 쓰기 보다 &lt;strong&gt;읽기 트래픽이 압도적으로 많다&lt;/strong&gt;는 글을 읽거나 실제로 경험해봤을 것이다.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MySQL InnoDB에서 읽기·쓰기 충돌부터 deadlock 로그 분석까지</title>
      <link>https://gukin.dev/posts/innodb-lock-conflict-deadlock-analysis/</link>
      <pubDate>Fri, 08 Aug 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/innodb-lock-conflict-deadlock-analysis/</guid>
      <description>&lt;h2 id=&#34;요약&#34;&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;MVVC는 트랜잭션 시작점을 기준으로 &lt;strong&gt;데이터 버저닝&lt;/strong&gt;을 한다&lt;/li&gt;
&lt;li&gt;락 종류에 따라 &lt;strong&gt;충돌 상황을 테스트&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;공유락은 말그대로 트랜잭션끼리 공유할 수 있다&lt;/li&gt;
&lt;li&gt;베타락은 말그대로 하나의 트랜잭션만 가진다&lt;/li&gt;
&lt;li&gt;공유락을 가진 상태로 업데이트, 삭제 등을 하면 베타락을 획득하려는 시도를 한다&lt;/li&gt;
&lt;li&gt;락 획득 대기 사이클이 생기면 데드락이 발생한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데드락을 최소화&lt;/strong&gt;하기 위한 락 설계 방법:
&lt;ul&gt;
&lt;li&gt;락을 잡는 순서를 트랜잭션 마다 동일하게 유지&lt;/li&gt;
&lt;li&gt;락 범위를 축소&lt;/li&gt;
&lt;li&gt;첫 쿼리 부터 for update로 가져오는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;배경&#34;&gt;배경&lt;/h2&gt;
&lt;p&gt;이번 주차는 낙관적 락과 비관적 락을 학습하게 되었다. 비관적 락은 흔히 느리지만 정합성이 중요할때 사용하며, 낙관적 락은 충돌 가능성이 낮을 때 상대적으로 빠른 상황을 요구할때 사용한다고 한다.&lt;/p&gt;</description>
    </item>
    <item>
      <title>DELETE-INSERT 패턴에서 발생하는 InnoDB Deadlock 분석</title>
      <link>https://gukin.dev/posts/delete-insert-innodb-deadlock/</link>
      <pubDate>Mon, 21 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://gukin.dev/posts/delete-insert-innodb-deadlock/</guid>
      <description>&lt;h2 id=&#34;배경&#34;&gt;배경&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;최근 우리 서비스는 Sentry를 통해 데드락 알람을 자주 받고 있다&lt;/li&gt;
&lt;li&gt;처음에는 중복 인덱스를 발견해서 제거하는 작업을 진행했다
&lt;ul&gt;
&lt;li&gt;그럼에도 불구하고 동일한 로직에서 데드락이 발생하는 중이다&lt;/li&gt;
&lt;li&gt;조금은 빈도가 감소했을 수 있는데, 데드락 모니터링과 수집 및 통계화를 다른 회사에서는 어떻게 하는지 리서치가 필요해 보인다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아무튼 데드락을 분석해보니, 동일한 레코드의 DELETE-INSERT가 하나의 트랜잭션 내 수행되는 API에서 발생하였다&lt;/li&gt;
&lt;li&gt;명확한 원인을 파악하고 전략을 세우기 위해 분석을 시도하였다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;innodb-deadlock-분석&#34;&gt;InnoDB Deadlock 분석&lt;/h2&gt;
&lt;h3 id=&#34;innodb-엔진-내부-상태를-확인하는-방법&#34;&gt;InnoDB 엔진 내부 상태를 확인하는 방법&lt;/h3&gt;
&lt;p&gt;RDMBS 클라이언트에서 위 명령어를 입력:&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
