| import { motion } from 'motion/react'; |
|
|
| export default function ACIDTransactionsDiagram() { |
| return ( |
| <motion.div |
| initial={{ opacity: 0, y: 24, scale: 0.97 }} |
| animate={{ opacity: 1, y: 0, scale: 1 }} |
| transition={{ duration: 0.7, ease: [0.25, 0.1, 0.25, 1] as const, delay: 0.2 }} |
| className="mt-10 mb-4" |
| > |
| <div className="text-center mb-6"> |
| <span className="text-lg font-bold uppercase tracking-widest text-indigo-400" style={{ filter: 'drop-shadow(0 0 10px rgba(99,102,241,0.5))' }}> |
| TRANSACTIONS & ACID PROPERTIES |
| </span> |
| </div> |
| <svg viewBox="0 0 900 760" className="w-full max-w-6xl mx-auto" style={{ filter: 'drop-shadow(0 0 30px rgba(99,102,241,0.1))' }}> |
| <defs> |
| <marker id="acidArr" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#6366f1" /></marker> |
| <marker id="acidRed" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#ef4444" /></marker> |
| <marker id="acidGrn" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#22c55e" /></marker> |
| <linearGradient id="acidHdr" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stopColor="rgba(99,102,241,0.2)" /><stop offset="100%" stopColor="rgba(99,102,241,0.05)" /></linearGradient> |
| </defs> |
| |
| {/* Header */} |
| <rect x="20" y="10" width="860" height="48" rx="12" fill="url(#acidHdr)" stroke="rgba(99,102,241,0.4)" strokeWidth="2" /> |
| <ellipse cx="50" cy="26" rx="13" ry="5" fill="none" stroke="#6366f1" strokeWidth="1.5" /> |
| <rect x="37" y="26" width="26" height="14" fill="rgba(99,102,241,0.1)" /> |
| <ellipse cx="50" cy="40" rx="13" ry="5" fill="none" stroke="#6366f1" strokeWidth="1.5" /> |
| <text x="72" y="28" fill="#818cf8" fontSize="10" fontWeight="700" fontFamily="'Inter',sans-serif">Transaction:</text> |
| <text x="148" y="28" fill="#a5b4fc" fontSize="9" fontFamily="'Inter',sans-serif">A sequence of database operations treated as a single logical unit of work.</text> |
| <text x="72" y="42" fill="#a5b4fc" fontSize="9" fontFamily="'Inter',sans-serif">All operations must succeed together, or all must fail β enforced by ACID properties.</text> |
| |
| {/* Lifecycle */} |
| <text x="450" y="80" textAnchor="middle" fill="#e2e8f0" fontSize="10" fontWeight="800" fontFamily="'Inter',sans-serif">TRANSACTION LIFECYCLE</text> |
| {[ |
| { x: 30, label: 'BEGIN', c: '#6366f1' }, |
| { x: 195, label: 'ACTIVE', c: '#22c55e' }, |
| { x: 360, label: 'PARTIALLY COMMITTED', c: '#3b82f6' }, |
| { x: 560, label: 'COMMITTED', c: '#4ade80' }, |
| ].map(({ x, label, c }, i) => ( |
| <g key={i}> |
| <rect x={x} y="88" width="140" height="30" rx="7" fill={`${c}22`} stroke={`${c}88`} strokeWidth="1.5" /> |
| <text x={x + 70} y="107" textAnchor="middle" fill={c} fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">{label}</text> |
| </g> |
| ))} |
| <line x1="170" y1="103" x2="195" y2="103" stroke="#6366f1" strokeWidth="1.5" markerEnd="url(#acidArr)" /> |
| <line x1="335" y1="103" x2="360" y2="103" stroke="#6366f1" strokeWidth="1.5" markerEnd="url(#acidArr)" /> |
| <line x1="500" y1="103" x2="560" y2="103" stroke="#22c55e" strokeWidth="1.5" markerEnd="url(#acidGrn)" /> |
| <rect x="360" y="128" width="110" height="26" rx="7" fill="rgba(239,68,68,0.12)" stroke="rgba(239,68,68,0.4)" strokeWidth="1.5" /> |
| <text x="415" y="144" textAnchor="middle" fill="#f87171" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">FAILED β ROLLBACK</text> |
| <line x1="430" y1="118" x2="430" y2="128" stroke="#ef4444" strokeWidth="1.5" markerEnd="url(#acidRed)" /> |
| |
| {/* A β Atomicity */} |
| <rect x="20" y="168" width="420" height="220" rx="12" fill="rgba(34,197,94,0.06)" stroke="rgba(34,197,94,0.4)" strokeWidth="2" /> |
| <circle cx="44" cy="192" r="14" fill="#22c55e" /> |
| <text x="44" y="197" textAnchor="middle" fill="white" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">A</text> |
| <text x="68" y="189" fill="#4ade80" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">ATOMICITY</text> |
| <text x="68" y="202" fill="#86efac" fontSize="8" fontFamily="'Inter',sans-serif">"All or Nothing"</text> |
| <text x="24" y="222" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">Every op in a transaction succeeds, or the entire</text> |
| <text x="24" y="234" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">transaction is rolled back with no partial changes.</text> |
| <text x="24" y="252" fill="#4ade80" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Example: Bank Transfer βΉ500 from A β B</text> |
| <rect x="24" y="259" width="175" height="80" rx="6" fill="rgba(34,197,94,0.08)" stroke="rgba(34,197,94,0.3)" strokeWidth="1" /> |
| <text x="111" y="274" textAnchor="middle" fill="#4ade80" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">β SUCCESS (COMMIT)</text> |
| <text x="34" y="290" fill="#86efac" fontSize="7.5" fontFamily="'Inter',sans-serif">1. Debit A: -βΉ500 β</text> |
| <text x="34" y="303" fill="#86efac" fontSize="7.5" fontFamily="'Inter',sans-serif">2. Credit B: +βΉ500 β</text> |
| <text x="34" y="316" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">Both written to disk</text> |
| <text x="34" y="330" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">A: βΉ1000ββΉ500 B: βΉ200ββΉ700</text> |
| <rect x="215" y="259" width="195" height="80" rx="6" fill="rgba(239,68,68,0.08)" stroke="rgba(239,68,68,0.3)" strokeWidth="1" /> |
| <text x="312" y="274" textAnchor="middle" fill="#f87171" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">β FAILURE (ROLLBACK)</text> |
| <text x="225" y="290" fill="#fca5a5" fontSize="7.5" fontFamily="'Inter',sans-serif">1. Debit A: -βΉ500 β</text> |
| <text x="225" y="303" fill="#f87171" fontSize="7.5" fontFamily="'Inter',sans-serif">2. Credit B: ERROR β</text> |
| <text x="225" y="316" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">Entire tx rolled back</text> |
| <text x="225" y="330" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">A stays βΉ1000, B stays βΉ200</text> |
| <text x="24" y="365" fill="#fbbf24" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Enforced by:</text> |
| <text x="90" y="365" fill="#94a3b8" fontSize="8" fontFamily="'Inter',sans-serif">Undo logs & Rollback mechanism</text> |
| <text x="24" y="378" fill="#fbbf24" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Ops:</text> |
| <rect x="50" y="369" width="55" height="14" rx="4" fill="rgba(34,197,94,0.2)" stroke="rgba(34,197,94,0.4)" strokeWidth="1" /> |
| <text x="77" y="379" textAnchor="middle" fill="#4ade80" fontSize="7" fontFamily="'Inter',sans-serif">COMMIT</text> |
| <rect x="112" y="369" width="62" height="14" rx="4" fill="rgba(239,68,68,0.2)" stroke="rgba(239,68,68,0.4)" strokeWidth="1" /> |
| <text x="143" y="379" textAnchor="middle" fill="#f87171" fontSize="7" fontFamily="'Inter',sans-serif">ROLLBACK</text> |
| |
| {/* C β Consistency */} |
| <rect x="460" y="168" width="420" height="220" rx="12" fill="rgba(59,130,246,0.06)" stroke="rgba(59,130,246,0.4)" strokeWidth="2" /> |
| <circle cx="484" cy="192" r="14" fill="#3b82f6" /> |
| <text x="484" y="197" textAnchor="middle" fill="white" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">C</text> |
| <text x="508" y="189" fill="#60a5fa" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">CONSISTENCY</text> |
| <text x="508" y="202" fill="#93c5fd" fontSize="8" fontFamily="'Inter',sans-serif">"Valid State to Valid State"</text> |
| <text x="468" y="222" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">A transaction brings the DB from one valid state</text> |
| <text x="468" y="234" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">to another β all integrity constraints are preserved.</text> |
| <text x="468" y="252" fill="#60a5fa" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Integrity Constraints that must hold:</text> |
| <rect x="468" y="258" width="390" height="95" rx="6" fill="rgba(15,23,42,0.4)" stroke="rgba(59,130,246,0.2)" strokeWidth="1" /> |
| {[ |
| { k: 'NOT NULL', v: 'Required fields must always have values', y: 0 }, |
| { k: 'UNIQUE', v: 'No duplicates in constrained columns', y: 1 }, |
| { k: 'CHECK', v: 'e.g. balance β₯ 0 β no negative balances', y: 2 }, |
| { k: 'FOREIGN KEY', v: 'Referenced rows must exist in parent table', y: 3 }, |
| { k: 'PRIMARY KEY', v: 'Must be unique and non-null', y: 4 }, |
| ].map(({ k, v, y }) => ( |
| <g key={y}> |
| <rect x="474" y={266 + y * 17} width="70" height="12" rx="3" fill="rgba(59,130,246,0.15)" stroke="rgba(59,130,246,0.3)" strokeWidth="0.5" /> |
| <text x="509" y={275 + y * 17} textAnchor="middle" fill="#93c5fd" fontSize="6.5" fontWeight="700" fontFamily="'Inter',sans-serif">{k}</text> |
| <text x="550" y={275 + y * 17} fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">{v}</text> |
| </g> |
| ))} |
| <text x="468" y="368" fill="#60a5fa" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Violation β transaction aborted automatically.</text> |
| <text x="468" y="381" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Consistency is the responsibility of both DB & application.</text> |
| |
| {/* I β Isolation */} |
| <rect x="20" y="400" width="420" height="340" rx="12" fill="rgba(168,85,247,0.06)" stroke="rgba(168,85,247,0.4)" strokeWidth="2" /> |
| <circle cx="44" cy="424" r="14" fill="#a855f7" /> |
| <text x="44" y="429" textAnchor="middle" fill="white" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">I</text> |
| <text x="68" y="421" fill="#c084fc" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">ISOLATION</text> |
| <text x="68" y="434" fill="#d8b4fe" fontSize="8" fontFamily="'Inter',sans-serif">"Transactions Don't Interfere"</text> |
| <text x="24" y="455" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">Concurrent transactions run as if they are serial.</text> |
| <text x="24" y="467" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">Intermediate states are hidden from other transactions.</text> |
| <text x="24" y="487" fill="#c084fc" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Isolation Levels (weakest β strongest):</text> |
| <rect x="24" y="494" width="385" height="92" rx="6" fill="rgba(15,23,42,0.4)" stroke="rgba(168,85,247,0.2)" strokeWidth="1" /> |
| {[ |
| { lv: 'READ UNCOMMITTED', note: 'Dirty Read allowed', c: '#f87171' }, |
| { lv: 'READ COMMITTED', note: 'Prevents Dirty Read', c: '#fbbf24' }, |
| { lv: 'REPEATABLE READ', note: 'Prevents Non-repeatable Read', c: '#60a5fa' }, |
| { lv: 'SERIALIZABLE', note: 'Prevents Phantom Read β safest', c: '#4ade80' }, |
| ].map(({ lv, note, c }, i) => ( |
| <g key={i}> |
| <rect x="30" y={500 + i * 21} width="160" height="14" rx="3" fill={`${c}20`} stroke={`${c}40`} strokeWidth="0.5" /> |
| <text x="110" y={510 + i * 21} textAnchor="middle" fill={c} fontSize="6.5" fontWeight="700" fontFamily="'Inter',sans-serif">{lv}</text> |
| <text x="198" y={510 + i * 21} fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif">{note}</text> |
| </g> |
| ))} |
| <text x="24" y="600" fill="#c084fc" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Read Phenomena:</text> |
| <text x="24" y="616" fill="#94a3b8" fontSize="8" fontFamily="'Inter',sans-serif">β’ Dirty Read: sees uncommitted data of another tx</text> |
| <text x="24" y="630" fill="#94a3b8" fontSize="8" fontFamily="'Inter',sans-serif">β’ Non-repeatable Read: same query returns different rows</text> |
| <text x="24" y="644" fill="#94a3b8" fontSize="8" fontFamily="'Inter',sans-serif">β’ Phantom Read: new rows appear in a repeated range query</text> |
| <text x="24" y="660" fill="#fbbf24" fontSize="7.5" fontFamily="'Inter',sans-serif">Implemented via: Locks, MVCC (Multi-Version Concurrency Control)</text> |
| <text x="24" y="673" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">Higher isolation = more serializable but lower concurrency performance.</text> |
| <text x="24" y="686" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">Most DBs default to READ COMMITTED or REPEATABLE READ.</text> |
| <text x="24" y="730" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">PostgreSQL: defaults to READ COMMITTED | MySQL InnoDB: REPEATABLE READ</text> |
| |
| {/* D β Durability */} |
| <rect x="460" y="400" width="420" height="340" rx="12" fill="rgba(245,158,11,0.06)" stroke="rgba(245,158,11,0.4)" strokeWidth="2" /> |
| <circle cx="484" cy="424" r="14" fill="#f59e0b" /> |
| <text x="484" y="429" textAnchor="middle" fill="white" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">D</text> |
| <text x="508" y="421" fill="#fbbf24" fontSize="13" fontWeight="800" fontFamily="'Inter',sans-serif">DURABILITY</text> |
| <text x="508" y="434" fill="#fcd34d" fontSize="8" fontFamily="'Inter',sans-serif">"Committed = Permanent"</text> |
| <text x="468" y="455" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">Once a transaction commits, changes persist forever</text> |
| <text x="468" y="467" fill="#e2e8f0" fontSize="8.5" fontFamily="'Inter',sans-serif">β even across crashes, power failures, or errors.</text> |
| <text x="468" y="487" fill="#fbbf24" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Techniques that ensure Durability:</text> |
| <rect x="468" y="494" width="385" height="92" rx="6" fill="rgba(15,23,42,0.4)" stroke="rgba(245,158,11,0.2)" strokeWidth="1" /> |
| {[ |
| { t: 'Write-Ahead Logging (WAL)', d: 'Log changes before applying to disk' }, |
| { t: 'Checkpointing', d: 'Periodically flush dirty pages to storage' }, |
| { t: 'Redo Logs', d: 'Replay committed txs after a crash' }, |
| { t: 'Shadow Paging', d: 'Keep old page until commit is confirmed' }, |
| ].map(({ t, d }, i) => ( |
| <g key={i}> |
| <text x="478" y={507 + i * 22} fill="#fbbf24" fontSize="7.5" fontWeight="700" fontFamily="'Inter',sans-serif">βΈ {t}</text> |
| <text x="478" y={518 + i * 22} fill="#94a3b8" fontSize="7" fontFamily="'Inter',sans-serif"> {d}</text> |
| </g> |
| ))} |
| <text x="468" y="600" fill="#fbbf24" fontSize="8.5" fontWeight="700" fontFamily="'Inter',sans-serif">Crash Recovery Flow:</text> |
| {[ |
| { label: 'CRASH', c: '#ef4444', x: 468 }, |
| { label: 'READ REDO LOG', c: '#fbbf24', x: 560 }, |
| { label: 'REPLAY COMMITS', c: '#3b82f6', x: 665 }, |
| { label: 'DB RESTORED β', c: '#4ade80', x: 775 }, |
| ].map(({ label, c, x }, i) => ( |
| <g key={i}> |
| <rect x={x} y="608" width="88" height="22" rx="5" fill={`${c}20`} stroke={`${c}50`} strokeWidth="1" /> |
| <text x={x + 44} y="622" textAnchor="middle" fill={c} fontSize="6.5" fontWeight="700" fontFamily="'Inter',sans-serif">{label}</text> |
| {i < 3 && <line x1={x + 88} y1="619" x2={x + 100} y2="619" stroke={c} strokeWidth="1.5" markerEnd="url(#acidArr)" />} |
| </g> |
| ))} |
| <text x="468" y="648" fill="#94a3b8" fontSize="8" fontFamily="'Inter',sans-serif">WAL ensures that crash recovery restores all committed changes.</text> |
| <text x="468" y="660" fill="#4ade80" fontSize="8" fontWeight="700" fontFamily="'Inter',sans-serif">Committed transactions are ALWAYS recoverable.</text> |
| <text x="468" y="680" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Used in: PostgreSQL (WAL), MySQL (InnoDB redo log),</text> |
| <text x="468" y="692" fill="#94a3b8" fontSize="7.5" fontFamily="'Inter',sans-serif">Oracle (REDO log files), SQL Server (Transaction Log)</text> |
| <text x="468" y="712" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">Storage media: SSDs and HDDs provide physical durability.</text> |
| <text x="468" y="724" fill="#64748b" fontSize="7" fontFamily="'Inter',sans-serif">For distributed systems: replication adds cross-node durability.</text> |
| <text x="468" y="740" fill="#fbbf24" fontSize="7.5" fontWeight="700" fontFamily="'Inter',sans-serif">Summary: ACID = the gold standard for reliable database transactions.</text> |
| </svg> |
| </motion.div> |
| ); |
| } |
|
|