<?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>Locking on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/locking/</link><description>Recent content in Locking on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 09:49:36 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/locking/index.xml" rel="self" type="application/rss+xml"/><item><title>Optimistic vs Pessimistic Locking: Detect-at-Commit vs Lock-Before-Access</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-optimistic-vs-pessimistic-locking-detect-at-commit-vs-lock-b/</link><pubDate>Sun, 06 Sep 2026 09:49:36 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-optimistic-vs-pessimistic-locking-detect-at-commit-vs-lock-b/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both are concurrency-control strategies for preventing lost updates when multiple transactions touch the same data, but they differ in when they deal with conflict. Optimistic locking assumes collisions are rare and only performs a &lt;strong class="kw"&gt;version check&lt;/strong&gt; at commit time, while pessimistic locking assumes collisions are likely and takes an &lt;strong class="kw"&gt;exclusive lock&lt;/strong&gt; before any read or write proceeds.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;text x="160" y="28" font-size="18" font-weight="bold" text-anchor="middle" style="fill:var(--primary)"&gt;Optimistic&lt;/text&gt;
&lt;text x="480" y="28" font-size="18" font-weight="bold" text-anchor="middle" style="fill:var(--primary)"&gt;Pessimistic&lt;/text&gt;
&lt;line x1="320" y1="45" x2="320" y2="335" stroke-width="1" stroke-dasharray="4,4" style="stroke:var(--border)"/&gt;
&lt;rect x="115" y="55" width="90" height="38" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="160" y="79" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Record (v1)&lt;/text&gt;
&lt;text x="160" y="105" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;no lock taken&lt;/text&gt;
&lt;line x1="140" y1="93" x2="75" y2="140" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;line x1="180" y1="93" x2="245" y2="140" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;rect x="30" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="75" y="165" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn A&lt;/text&gt;
&lt;rect x="200" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="245" y="165" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn B&lt;/text&gt;
&lt;line x1="75" y1="180" x2="75" y2="225" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;line x1="245" y1="180" x2="245" y2="225" stroke-width="1.5" stroke-dasharray="3,3" style="stroke:var(--border)"/&gt;
&lt;rect x="30" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="75" y="245" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;v1 &amp;#8594; v2&lt;/text&gt;
&lt;text x="75" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;committed&lt;/text&gt;
&lt;rect x="200" y="225" width="90" height="40" rx="4" stroke-width="1.5" stroke-dasharray="3,3" style="fill:none;stroke:var(--border)"/&gt;
&lt;text x="245" y="245" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;v1 &amp;#8800; v2&lt;/text&gt;
&lt;text x="245" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict, retry&lt;/text&gt;
&lt;text x="160" y="310" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict caught at commit time&lt;/text&gt;
&lt;rect x="470" y="34" width="20" height="14" rx="2" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;path d="M474,34 v-5 a6,6 0 0 1 12,0 v5" stroke-width="1.5" style="fill:none;stroke:var(--compare-b)"/&gt;
&lt;rect x="435" y="55" width="90" height="38" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="480" y="79" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Record&lt;/text&gt;
&lt;line x1="460" y1="93" x2="395" y2="140" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;line x1="500" y1="93" x2="565" y2="140" stroke-width="1.5" stroke-dasharray="3,3" style="stroke:var(--border)"/&gt;
&lt;text x="545" y="120" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;blocked&lt;/text&gt;
&lt;rect x="350" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="395" y="157" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn A&lt;/text&gt;
&lt;text x="395" y="171" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;holds lock&lt;/text&gt;
&lt;rect x="520" y="140" width="90" height="40" rx="4" stroke-width="1.5" stroke-dasharray="3,3" style="fill:none;stroke:var(--border)"/&gt;
&lt;text x="565" y="157" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn B&lt;/text&gt;
&lt;text x="565" y="171" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;waiting&lt;/text&gt;
&lt;line x1="395" y1="180" x2="395" y2="225" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;line x1="565" y1="180" x2="565" y2="225" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;rect x="350" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="395" y="245" font-size="11" text-anchor="middle" style="fill:var(--content)"&gt;commits &amp;amp;&lt;/text&gt;
&lt;text x="395" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;releases lock&lt;/text&gt;
&lt;rect x="520" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="565" y="245" font-size="11" text-anchor="middle" style="fill:var(--content)"&gt;acquires lock&lt;/text&gt;
&lt;text x="565" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;then runs&lt;/text&gt;
&lt;text x="480" y="310" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict prevented up front&lt;/text&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Optimistic Locking&lt;/th&gt;
&lt;th&gt;Pessimistic Locking&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Access phase&lt;/td&gt;
&lt;td&gt;No lock taken; any transaction can read or begin writing the row immediately&lt;/td&gt;
&lt;td&gt;Lock acquired (e.g. SELECT FOR UPDATE) before the transaction reads or writes the row&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrent access&lt;/td&gt;
&lt;td&gt;Other transactions freely read and write the same row in parallel&lt;/td&gt;
&lt;td&gt;Other transactions attempting the same row must wait for the lock holder to finish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conflict detection timing&lt;/td&gt;
&lt;td&gt;Deferred until commit, via a version number, timestamp, or hash comparison&lt;/td&gt;
&lt;td&gt;Not needed as a separate step; the lock physically prevents overlapping access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On conflict&lt;/td&gt;
&lt;td&gt;Commit is rejected; the transaction is rolled back and typically retried&lt;/td&gt;
&lt;td&gt;No conflict occurs; the waiting transaction simply blocks until the lock is released&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation mechanism&lt;/td&gt;
&lt;td&gt;Application-level version column checked in the UPDATE&amp;rsquo;s WHERE clause&lt;/td&gt;
&lt;td&gt;Database-level row or table locks managed by the lock manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput under low contention&lt;/td&gt;
&lt;td&gt;High; no blocking overhead when collisions are rare&lt;/td&gt;
&lt;td&gt;Lower; locking overhead is paid even when no real conflict would occur&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavior under high contention&lt;/td&gt;
&lt;td&gt;Retry storms and wasted work as many transactions repeatedly fail and re-run&lt;/td&gt;
&lt;td&gt;Orderly queueing keeps correctness but serializes work and limits parallelism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deadlock risk&lt;/td&gt;
&lt;td&gt;None, since no locks are ever held&lt;/td&gt;
&lt;td&gt;Possible when transactions acquire multiple locks in inconsistent order&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Optimistic locking detects conflicts at &lt;strong class="kw"&gt;commit time&lt;/strong&gt;; pessimistic locking prevents them via &lt;strong class="kw"&gt;upfront locking&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Optimistic locking never blocks other transactions, it only forces a &lt;strong class="kw"&gt;retry&lt;/strong&gt; on collision.&lt;/li&gt;
&lt;li&gt;Pessimistic locking holds an &lt;strong class="kw"&gt;exclusive lock&lt;/strong&gt; for the transaction&amp;rsquo;s full duration, serializing access to the row.&lt;/li&gt;
&lt;li&gt;Optimistic locking carries no &lt;strong class="kw"&gt;deadlock&lt;/strong&gt; risk because it never holds locks.&lt;/li&gt;
&lt;li&gt;Pessimistic locking trades raw throughput for &lt;strong class="kw"&gt;predictability&lt;/strong&gt; when contention is heavy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Optimistic Locking&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>