✏️ धडा 04 — Writes आणि transactions: pencil ने लिहिलेली खातेवही
📍 तुम्ही इथे आहात: 18 पैकी धडा 04 · मागे: lesson-03-sql-reads · पुढे: lesson-05-data-modelling
📦 या ब्रँचमध्ये काय आहे
धडे 01–03, आणि नोंदवह्या सुरक्षितपणे बदलणे: INSERT, UPDATE, DELETE,
आणि transaction — BEGIN … COMMIT, किंवा ROLLBACK — जे ACID ची चार
वचने खरी करते.
🧒 5 वर्षांच्या मुलाला समजावल्यासारखे
ऐश्वर्याला 3A मधून 3B मध्ये हलवणे म्हणजे दोन नोंदवह्यांमधील दोन ओळी: तिचा class pointer बदला, आणि वर्गांची संख्या update करा. दोन्हींच्या मध्येच वीज गेली तर? अर्धे स्थलांतर — ऐश्वर्या 3B मध्ये, पण संख्या अजूनही 3A सांगते.
म्हणून दप्तरदार आधी pencil ने लिहितो ✏️. BEGIN pencil उघडते. दोन्ही बदल
लिहिले जातात. काहीही बिघडले — error, नाकारलेला pointer, crash — तर दप्तरदार
सगळे खोडून टाकतो (ROLLBACK) आणि नोंदवह्या अगदी पूर्वीसारख्या दिसतात. दोन्ही
ओळी बरोबर असतील तेव्हाच दप्तरदार त्यांच्यावर शाईने (COMMIT) गिरवतो, एकदम
सगळे, म्हणजे त्यानंतर वीज गेली तरी दोन्ही बदल कपाटात राहतात.
हेच transaction, आणि त्याच्या चार वचनांतून ACID बनते:
- Atomic — सगळ्या ओळी किंवा एकही नाही.
- Consistent — शाई वाळल्यानंतरही प्रत्येक constraint पाळला जातो.
- Isolated — इतर clerks ना तुमच्या pencil खुणा दिसत नाहीत (धडा 07).
- Durable — शाई वीज गेल्यावरही टिकते.
🗺️ आकृती
flowchart LR
b["✏️ BEGIN<br/>UPDATE students SET class_id = 2 WHERE id = 1"]
u2["UPDATE students SET class_id = 99 WHERE id = 4<br/>💥 FOREIGN KEY constraint failed"]
rb["↩️ ROLLBACK<br/>both pencil marks erased — nothing changed"]
ok["✅ COMMIT<br/>ink: all of it, at once, durable"]
b --> u2 -.->|"1 any error"| rb
b -.->|"2 no errors"| ok
❓ काय
INSERT INTO students (name, roll_no, class_id) VALUES (…),UPDATE students SET class_id = 2 WHERE id = 1,DELETE FROM students WHERE id = 5.UPDATE/DELETEवर नेहमी आधीWHEREलिहा — त्याशिवाय प्रत्येक row बदलते.BEGIN/COMMIT/ROLLBACK. Python मध्ये:with conn:block च्या शेवटी commit करतो आणि exception बाहेर पडला तर rollback करतो —txn()मधील हीच पद्धत.- Autocommit = प्रत्येक statement स्वतःचे transaction. एका ओळीसाठी ठीक; एकमेकांशी जुळायला हव्यात अशा दोन ओळींसाठी चुकीचे.
- Durability ची किंमत म्हणजे प्रत्येक commit ला एक disk sync; म्हणूनच 1,000 inserts असलेले एक transaction 1,000 transactions पेक्षा कितीतरी जलद असते.
- Constraint failures write च्या वेळीच होतात (
IntegrityError) — धडा 02 मधील schema transaction च्या आत लागू होतो, म्हणून एक नाकारलेली ओळ संपूर्ण pencil मागे घेते.
🤔 का
कारण पैसे, प्रवेश, साठा आणि bookings हे सगळे "एकमेकांशी जुळायला हव्यात अशा दोन ओळी" आहेत, आणि जगातले सर्वात महागडे bugs म्हणजे अर्धवट transactions. खोडरबर हाच "काहीतरी चुकले" आणि "काहीतरी चुकले आणि आता data खोटे बोलतो" यांतील फरक आहे.
🔧 कसे (या repo मध्ये)
db/demo.py मधील txn(): दोन UPDATE असलेला एक with c:
block, ज्यातला दुसरा अस्तित्वात नसलेल्या वर्गाकडे बोट दाखवतो. दोन्ही बदल गायब
होताना पाहा.
🧪 करून पाहा
python3 db/demo.py txn
python3 - <<'EOF'
import sqlite3; c = sqlite3.connect("db/school.db"); c.execute("PRAGMA foreign_keys = ON")
with c: # one transaction: enrol + first grade
cur = c.execute("INSERT INTO students (name, roll_no, class_id) VALUES ('Zoya', '3B-03', 2)")
c.execute("INSERT INTO grades (student_id, subject, term, grade) VALUES (?, 'maths', 1, 'A')", (cur.lastrowid,))
print(c.execute("SELECT s.name, g.grade FROM students s JOIN grades g ON g.student_id = s.id WHERE s.name='Zoya'").fetchall())
try:
with c: c.execute("DELETE FROM students") # 😱 no WHERE — but inside a transaction…
# (it committed! there was no error.) Restore:
except Exception as e: print(e)
EOF
python3 db/demo.py >/dev/null && echo "room rebuilt"
✅ तपासा — तुम्हाला काय दिसायला हवे
txn अयशस्वी transfer च्या आधी आणि नंतर त्याच दोन rows छापतो — दोन्ही updates खोडले गेले. तुमचा प्रवेश [('Zoya', 'A')] छापतो. WHERE शिवायचा DELETE यशस्वी होतो (error नाही, म्हणून rollback नाही) — तुम्ही पुन्हा बनवेपर्यंत खोली रिकामी राहते: transaction errors पासून वाचवते, चुकांपासून नाही; त्यांच्यासाठी धडा 09 आहे.
🏁 तुम्ही आत्ताच काय सिद्ध केले
अयशस्वी transaction कोणतेही अर्धे स्थलांतर मागे ठेवत नाही, यशस्वी transaction एकदम सगळे उतरवते — आणि बरोबर-पण-चुकीचे statement तरीही commit होते, म्हणूनच backups असतात.
⚠️ नेहमीच्या चुका
WHEREशिवायUPDATE/DELETE(आधीWHEREलिहा, मग क्रियापद)- loop मध्ये प्रत्येक transaction ला एकच statement — हजार disk syncs
- user विचार करत असताना locks धरून ठेवणारी लांब transactions (धडा 07)
- block च्या आत exception पकडून पुढे चालू ठेवणे — exception बाहेर पडला तरच rollback होतो
🏭 प्रत्यक्ष वापरात हे का महत्त्वाचे: payment systems म्हणजे वरपासून खालपर्यंत transactions; "आम्ही दोनदा पैसे कापले" आणि "order आहे पण stock हलला नाही" ही दोन्ही हरवलेल्या
BEGINची लक्षणे. Frameworks pencil ला@transactionalमागे लपवतात — ते काय काढते ते जाणून घ्या.
⏭️ पुढे
प्रत्येक माहिती कुठे राहावी? Data modelling — एक तथ्य, एक जागा, आणि हा नियम मुद्दाम कधी मोडायचा.
git checkout lesson-05-data-modelling