<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>chungjung-d.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 28 Sep 2022 02:42:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>chungjung-d.log</title>
            <url>https://velog.velcdn.com/images/chungjung-d/profile/50d67f9d-b564-4dd2-9b0f-5488841e1ee6/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. chungjung-d.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/chungjung-d" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Database] Transaction Isolation level]]></title>
            <link>https://velog.io/@chungjung-d/Database-Transaction-Isolation-level</link>
            <guid>https://velog.io/@chungjung-d/Database-Transaction-Isolation-level</guid>
            <pubDate>Wed, 28 Sep 2022 02:42:34 GMT</pubDate>
            <description><![CDATA[<h1 id="introduction">Introduction</h1>
<h3 id="이전-글">이전 글</h3>
<p><a href="https://velog.io/@chungjung-d/Database-Transaction-ACID"> <strong>1. [Database] Transaction ACID</strong></a></p>
<p>Transaction ACID에 이어서 이번에는 Transaction Isolation Level에 대해서 다뤄보려고 합니다. Isolation Level에 대한 정의는 SQL-92를 기준으로 작성했습니다. </p>
<h1 id="transaction-isolation-level">Transaction Isolation Level</h1>
<p><strong>트랜잭션 격리 수준(Transaction isolation level)</strong>의 정의는 2021/11/03에 작성된 Microsoft ODBC문서를 참고했습니다. </p>
<blockquote>
<p>Transaction isolation levels are a measure of the extent to which transaction isolation succeeds. In particular, transaction isolation levels are defined by the presence or absence of the following phenomena: Dirty Read, Nonrepeatable Reads, Phantoms</p>
</blockquote>
<p><a href="https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/transaction-isolation-levels?view=sql-server-ver16">- Microsoft ODBC -</a></p>
<p>간단하게 해석하면, &quot;<strong>트랜잭션 격리수준은 트랜잭션 격리가 성공하는 정도에 따라 나뉘며, 주로 Dirty Read, Nonrepeatable Read, Phantoms과 같은 현상의 유무</strong>에 따라서 결정됨&quot; 정도로 해석 할 수 있을 것 같습니다.</p>
<p>다만 조금 더 이해를 쉽게 하기 위해서, <strong>특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정</strong>한다고 생각하셔도 좋습니다.</p>
<h3 id="acid-원칙이랑-위배되는-것-같은데">ACID 원칙이랑 위배되는 것 같은데....?</h3>
<p> ACID원칙을 실제 상황에서 만족시키기 위해서는 동시성이 너무 떨어지기 때문에, 이를 일부 무시하여 동시성을 확보하기 위한 현실적인 대안이 Transaction Isolation Level이라고 생각할 수 있습니다. 격리 수준이 낮을수록 더 높은 동시성을 보장하고, 높을수록 더 동시성이 낮아지지만 데이터의 정합성을 보장합니다. </p>
<p>그러면 이제 Dirty Read와 같은 현상이 무엇이며, 트랜잭션의 격리 수준에는 무엇이 있는지 알아보겠습니다. </p>
<h3 id="🚫주의사항">🚫주의사항</h3>
<blockquote>
<p>트랜잭션 격리 수준에 대한 <strong>문서는 오로지 Microsoft의 ODBC문서만 참고할 생각입니다</strong>. 자료를 이것 저것 찾다보니, MySQL이나 PSQL같은 실제 사용되고 있는 DB에서 쓰이는 방식이 섞이면 Transaction isolation level과 격리 수준에 따라서 발생하는 현상이 달라집니다. </p>
<p>따라서 MySQL이나 PSQL의 transaction isolation 동작 방식은 다른 포스터에서 다룰 생각입니다.</p>
</blockquote>
<hr>
<h2 id="🔒-read-lock--write-lock">🔒 Read Lock &amp; Write Lock</h2>
<p>시작하기에 앞서서 먼저 Read Lock과 Wirte Lock에 대해서 알아야 합니다. </p>
<p><strong>Read Lock</strong>의 경우 특정 행에 Read Lock이 걸리면 Read 요청은 통과시키고 Write 요청은 대기 시킵니다. 만약 Read Lock이 걸려서 Write 요청이 블럭되고 있다면, 그 뒤에 들어온 Read 요청은 먼저 들어온 Write 요청이 처리되기 전까지 대기시킵니다. </p>
<p>** Write Lock**의 경우 특정 행을 수정하거나 지울 경우 그 행에 대해서 걸리는 Lock이다. 이 경우 모든 요청을 블럭시게 된다. </p>
<h2 id="🔒lv0-read-uncommitted">🔒[Lv.0] Read Uncommitted</h2>
<ul>
<li><strong>Read Uncommitted</strong> 혹은 <strong>Level 0</strong> 의 격리 수준이라고 합니다.</li>
<li>각 트랜잭션에서 변경내용이 COMMIT 혹은 ROLLBACK된 여부에 상관없이, 다른 트랜잭션에서 값을 조회할 수 있습니다. </li>
<li><strong>Dirty Read</strong> 현상이 발생합니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/chungjung-d/post/092403e0-9b20-4814-95a8-eb7eaf3aea7f/image.png" alt=""></p>
<p>위의 그림과 같이 Transaction-1에서 Busan이라는 데이터를 넣었고 아직 COMMIT이 발생하지 않았음에도 불구하고 다른 트랜잭션인 Trnascation-2에서 Busan이라는 데이터를 조회할 수 있습니다. </p>
<h3 id="dirty-read">Dirty Read</h3>
<p>위와 같이 하나의 트랜잭션이 완료되기도 전에 다른 트랜잭션에서 그 값을 볼 수 있게 되는 현상을 <strong>Dirty Read</strong>라고 합니다.</p>
<h2 id="🔒lv1-read-committed">🔒[Lv.1] Read Committed</h2>
<ul>
<li><p><strong>Read Committed</strong> 혹은 <strong>Level 1</strong> 의 격리 수준이라고 합니다.</p>
</li>
<li><p>주로 대부분의 RDB에서 Default로 사용되고 있는 트랜잭션 격리 수준입니다. (하지만 구현 방식은 모두 제각각 다릅니다.)</p>
</li>
<li><p><a href="https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/transaction-isolation-levels?view=sql-server-ver16">ODBC</a>에서는 Read Committed의 구현을 다음과 같이 설명하고 있습니다.</p>
<blockquote>
<p><strong>[조회] Only Read the row</strong>
조회만 하는 트랜잭션일 경우, 현재 읽고 있는 행에 Read Lock을 건다. 그 후에 현재 행에 대한 조회가 끝나면 다음 행에 Read Lock을 걸고 현재 Read Lock이 걸린 행의 잠금을 해제합니다.
즉 현재 행에 대한 <strong>조회가 끝나면 다른 트랜잭션에서 조회가 끝난 행을 수정 혹은 삭제 할 수 있습니다.</strong></p>
</blockquote>
<blockquote>
<p><strong>[수정 &amp; 삭제] Update &amp; Delete the row</strong>
특정 행을 수정하고 삭제하는 경우에는 수정 및 삭제하는 행에 Write Lock을 겁니다. 그리고 트랜잭션이 COMMIT 혹은 ROLLBACK되기 전까지 계속 Write Lock을 유지해서 다른 트랜잭션에 해당 행에 접근할 수 없도록 만듭니다. </p>
</blockquote>
</li>
</ul>
<p>ODBC와 같은 방식을 사용할 경우 UNDO영역에 저장하거나 DB의 Sanpshot을 찍는 등과 같은 방법은 사용하지 않습니다. 이와 같은 방법들은 MySQL과 같은 DB에서 새롭게 구현한 방식입니다. </p>
<h3 id="nonrepeatable-read">Nonrepeatable Read</h3>
<p>이와 같은 격리수준에서는 Notrepatable Read 현상이 나타날 수 있다. 이는 한 트랜잭션에서 조회를 두 번 했을 때, 행의 데이터가 달라짐을 의미합니다. </p>
<p><img src="https://velog.velcdn.com/images/chungjung-d/post/5ed3e023-6f7c-4008-9e85-9f3a1d91523d/image.png" alt=""></p>
<p>위의 사진과 같이 조회 중에 Read Lock을 걸고 조회를 마치고 Read Lock을 해재한 사이에 다른 트랜잭션에서 특정 행에 Update를 하고 완료를 했다면, 그 행을 다시 읽을 때 값이 다른 현상이 나타나게 됩니다.</p>
<p>이는 한 트랜잭션에서 같은 조회를 했을 때 값이 일정해야 한다는 것에 어긋나게 됩니다. </p>
<h2 id="🔒lv2-repeatable-read">🔒[Lv.2] Repeatable Read</h2>
<ul>
<li><p><strong>Repeatable Read</strong> 혹은 <strong>Level 2</strong> 의 격리 수준이라고 합니다.</p>
</li>
<li><p>ODBC에서는 Repeatable Read의 구현을 다음과 같이 설명하고 있습니다.</p>
<blockquote>
<p><strong>[조회] Only Read the row</strong>
프로그램으로부터 반환될 모든 행에 대해서 Read Lock을 걸고 유지합니다. 즉 조회하는 트랜잭션이 끝날 때 까지 Read하는 요청을 제외하고 행에 접근할 수 없습니다 </p>
</blockquote>
<blockquote>
<p><strong>[수정 &amp; 삭제] Update &amp; Delete the row</strong>
수정하고 삭제하는 경우에 대해서는 접근하는 모든 행에 대해서 Write Lock을 겁니다. 이를 걸기 때문에 다른 어떤 요청도 트랜잭션이 완료되기 전까지 행에 접근할 수 없습니다. </p>
</blockquote>
</li>
</ul>
<p>위와 같은 방식으로 Read Lock 자체를 유지하기 때문에, Nonrepeatable Read 현상을 방지할 수 있습니다. </p>
<h3 id="phantom-read">Phantom Read</h3>
<p>Repeatable Read의 문제는 이와 같이 <strong>row에 대해서만 잠금을 거는데서 시작합니다.</strong> 잡금을 거는 범위가 행에 국한되기 때문에 새로운 행이 Instert 되는데 대응하지 못합니다. 
<img src="https://velog.velcdn.com/images/chungjung-d/post/3967f794-9842-401a-8fc8-54474449eda2/image.png" alt=""></p>
<p>사진과 같이 Transaction-1이 다시 한 번 조회를 했을 때, 보이지 않던 행이 보이게 되는 현상이 일어납니다.</p>
<h2 id="🔒lv3-serializable">🔒[Lv.3] Serializable</h2>
<ul>
<li><p><strong>Serializable</strong> 혹은 <strong>Level 3</strong> 의 격리 수준이라고 합니다.</p>
</li>
<li><p>ODBC에서는 Serializable의 구현을 다음과 같이 설명하고 있습니다.</p>
<blockquote>
<p><strong>[조회] Only Read the row</strong>
조회가 될 가능성이 있는 행 범위 전체에 대해서 Read Lock을 걸고 유지합니다. 예를 들어서 <strong>SELECT * FROM Orders</strong> 구문이 있다면, Orders 테이블 전체에 걸쳐서 Read Lock을 걸어서 다른 트랜잭션에서 행에 접근해서 내용을 수정할 수 없게 막어버립니다. </p>
</blockquote>
<blockquote>
<p><strong>[수정 &amp; 삭제] Update &amp; Delete the row</strong>
수정이나 삭제할 때도 마찬가지로 영향을 미칠수 있는 모든 범위에 Wirite Lock을 겁니다. </p>
</blockquote>
</li>
</ul>
<p>이와 같은 방법을 이용하면 확실하게 데이터의 정합성을 보장할 수 있지만, 동시성을 매우 떨어트립니다. </p>
<h2 id="conclusion">Conclusion</h2>
<p>현재 작성한 문서는 ODBC문서를 기반으로 해석한 글에 불과합니다. 실제 MySQL이나 PostgreSQL 그리고 실제로 사용되는 다양한 Database들은 더 발전된 방식을 사용하고 있는 것으로 알고 있습니다. 그렇기 때문에 이와 같은 방식의 Database의 작동방식으로 설명하기에는 Phantom Read와 같은 문제가 왜 발생하는지 설명하기 어려웠습니다.</p>
<p>그래서 각 데이터베이스들에 대한 트랜잭션 격리 수준에 대해서는 다음 포스팅에서 알아보기로 하고, 이번에는 조금 개념적으로 접근해서 정리해 보았습니다. </p>
<h1 id="reference">Reference</h1>
<p><a href="https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/transaction-isolation-levels?view=sql-server-ver16">https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/transaction-isolation-levels?view=sql-server-ver16</a></p>
<p><a href="https://csharp-video-tutorials.blogspot.com/2015/08/non-repeatable-read-example-in-sql.html">https://csharp-video-tutorials.blogspot.com/2015/08/non-repeatable-read-example-in-sql.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Database] Transaction & ACID]]></title>
            <link>https://velog.io/@chungjung-d/Database-Transaction-ACID</link>
            <guid>https://velog.io/@chungjung-d/Database-Transaction-ACID</guid>
            <pubDate>Mon, 26 Sep 2022 10:07:37 GMT</pubDate>
            <description><![CDATA[<h1 id="introduce">Introduce</h1>
<p> 개발을 하면서 Transaction이라는 개념을 참 많이 사용한 것 같은데, 실제로  내가 그 개념을 제대로 이해하고 있는지에 대해서 의문이 들어서 Transaction에 대해서 조금 정리하는 시간을 가져보려고 합니다. </p>
<p>Transaction과 ACID 그리고 Isolation Level까지 어렴풋이만 알았던 개념들을 이참에 블로그 글로 정리하면서 알아보려고 합니다. 처음 글은 ACID까지만 다루고, 그 뒤에 Isolation Level에 대해서 다뤄보고자 합니다. </p>
<p>혹시 틀린 점이나, 잘못된 부분이 있으면 지적 부탁드릴게요</p>
<h1 id="transaction">Transaction</h1>
<blockquote>
<p>DB에서 트랜젝션은 &quot;여러개의 작업을 하나로 묶어서 실행하는 작업 수행의 논리적 단위&quot; 라고 할 수 있습니다.</p>
</blockquote>
<p>조금 풀어서 설명해 볼게요. 예를 들어서 A가 친구 B에서 10000원을 송금하는 상황을 생각해 봅시다. 이런 상황에서는 <strong>A의 통장에서 돈이 빠져나가는 출금 1번, B의 통장으로 돈이 들어오는 입금 1번이</strong> 각각 진행되게 됩니다. </p>
<p>*<em>트랜잭션을 사용하지 않을 경우 *</em> , 만약 A의 통장에서 돈이 빠져나갔고, 돈이 계좌에서 빠져나간 사실이 은행 DB에 저장이 되었지만, 네트워크 장애로 인해서 B에게 입금이 되지 않는 상황이 발생했다고 합시다. </p>
<p>이 경우 은행 DB에는 통장 출금 기록만 남고 입금 기록은 남지 않는 참사가 발생하게 됩니다. </p>
<p><strong>트랜잭션을 사용한 경우</strong> 위와 같은 상황에서 입금과 출금을 하나의 작업으로 묶어서 처리하기 때문에 만약 입금이 실패했을 경우 A의 출금기록을 Rollback 시키게 됩니다.</p>
<p>*<em>즉 트랜젝션을 사용하는 이유는 데이터의 정합성을 보장하기 위해서 사용하는 것입니다. *</em></p>
<h1 id="acid">ACID</h1>
<p>트랜잭션은 DB의 정합성을 보장하기 위해서 4가지 특성을 만족해야 하는데, 이 4가지 특성의 앞글자를 따서 ACID라고 부릅니다.</p>
<blockquote>
<p>다만 제 경험상, 완벽하게 Isolation을 만족하는 Transaction을 모든 곳에서 사용하지는 않았던 것 같아서 가이드라인 정도로 생각하면 좋을 것 같아요. </p>
</blockquote>
<p>이 부분은 혹시 제 생각이 틀릴수도 있을 것 같아서, 다른 의견이 있다면 댓글로 달아주시면 정말 감사할 것 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/chungjung-d/post/616e5e6f-df01-4c08-8336-a72ac48677b3/image.png" alt=""></p>
<p>트랜잭션은 위에서 말했듯이 4가지 특성 <strong>Atomicity</strong>, <strong>Consistency</strong>, <strong>Isolation</strong>, <strong>Durability</strong>를 만족합니다. </p>
<h3 id="atomicity-원자성">Atomicity [원자성]</h3>
<blockquote>
<p>트랜잭션내에 묶여있는 작업이 일부만 실행되거나 중단되지 않는 것을 보장합니다. 즉 All or Notion, 전체 다 수행되거나 아니면 아예 수행되지 않거나를 보장합니다.</p>
</blockquote>
<h3 id="consistency-일관성">Consistency [일관성]</h3>
<blockquote>
<p>기존의 DB와 Transaction후의 DB가 consistent 해야 한다. 즉 일관성을 유지해야 합니다.</p>
</blockquote>
<blockquote>
<p>조금 더 풀어서 설명하면, <strong>기존의 DB에서 설정한 제약 조건들에 만족하도록 항상 유지되어야 한다는 것입니다.</strong> 만약 특정 column에 Int 타입만 들어갈 수 있다면 float 타입의 값이 들어가서는 안됩니다. </p>
</blockquote>
<h3 id="isolation-격리성">Isolation [격리성]</h3>
<blockquote>
<p>각 트렌잭션 끼리는 서로 격리되어야 합니다. 즉 서로 다른 트렌잭션끼리는 서로 간섭할 수 없습니다. </p>
</blockquote>
<h3 id="durability-지속성">Durability [지속성]</h3>
<blockquote>
<p>성공적으로 트랜잭션이 수행되었다면 영원이 반영이 되어야 합니다. 즉 Commit을 하게 되면 트랜잭션은 영원히 반영됩니다.</p>
</blockquote>
<p>다음 글에서는 Transaction Isolation Level에 대해서 다뤄보도록 하겠습니다.</p>
<h1 id="reference">Reference</h1>
<h2 id="image">Image</h2>
<p><a href="https://www.geeksforgeeks.org/acid-properties-in-dbms/">https://www.geeksforgeeks.org/acid-properties-in-dbms/</a></p>
<h2 id="docs">Docs</h2>
<p><a href="https://www.geeksforgeeks.org/acid-properties-in-dbms/">https://www.geeksforgeeks.org/acid-properties-in-dbms/</a>
<a href="https://victorydntmd.tistory.com/129">https://victorydntmd.tistory.com/129</a></p>
]]></description>
        </item>
    </channel>
</rss>