Student starter code (30% baseline)
index.html- Main HTML pagescript.js- JavaScript logicstyles.css- Styling and layoutpackage.json- Dependenciessetup.sh- Setup scriptREADME.md- Instructions (below)๐ก Download the ZIP, extract it, and follow the instructions below to get started!
By completing this lab, you will:
# 1. Navigate to the SQLite folder
cd sqlite
# 2. Create database and load schema
sqlite3 banking.db < schema.sql
# 3. Run the working examples
sqlite3 banking.db < transactions.sql
# You should see transaction demos running immediately!
# 1. Start PostgreSQL and pgAdmin
docker-compose up -d
# 2. Access pgAdmin at http://localhost:5052
# Email: admin@telebortbank.com
# Password: admin123
# 3. Connect to PostgreSQL server:
# Host: postgres (in pgAdmin) or localhost:5435 (from host)
# Username: bankadmin
# Password: secure_password_123
This template includes a TelebortBank system with transaction demos:
One. Banking Database Schema (schema.sql)
2. Transaction Safety Demos (transactions.sql)
3. Docker PostgreSQL Setup (docker-compose.yml)
Scenario: Multiple users try to update the same account simultaneously.
Location: sqlite/transactions.sql (search for -- TODO 1)
Success Criteria:
Example Flow:
-- User A reads account (version = 1)
-- User B reads account (version = 1)
-- User A updates successfully (version = 2)
-- User B's update should FAIL (version mismatch)
Hints:
WHERE version = ? in UPDATE statementchanges() function to verify update succeededScenario: Two ATMs try to withdraw from the same account at the same time.
Location: sqlite/transactions.sql (search for -- TODO 2)
Success Criteria:
Example Flow:
-- Account balance: $1000
-- ATM 1: Withdraw $700 (should succeed)
-- ATM 2: Withdraw $500 (should fail - insufficient funds)
-- Final balance: $300
Hints:
BEGIN IMMEDIATE for write transactionsROLLBACK if balance check failsScenario: Two transfers happen simultaneously in opposite directions.
Location: sqlite/transactions.sql (search for -- TODO 3)
Success Criteria:
Example Flow:
-- Transaction 1: Transfer $100 from Account A to Account B
-- Transaction 2: Transfer $50 from Account B to Account A
-- Without ordering: DEADLOCK!
-- With ordering: Both succeed
Hints:
ORDER BY account_id when selecting for updateSELECT FOR UPDATE explicitlyTerminal 1:
sqlite3 banking.db
.mode column
.headers on
BEGIN IMMEDIATE;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Wait 10 seconds before COMMIT
COMMIT;
Terminal 2 (within 10 seconds):
sqlite3 banking.db
BEGIN IMMEDIATE;
UPDATE accounts SET balance = balance - 50 WHERE account_id = 1;
-- This will be blocked until Terminal 1 commits
COMMIT;
# Terminal 1
docker exec -it w4-postgres psql -U bankadmin -d telebortbank
# Terminal 2
docker exec -it w4-postgres psql -U bankadmin -d telebortbank
# Run competing transactions in both terminals
Want to go further? Try these advanced exercises:
Create an audit_log table that records:
Bonus: Use triggers to automate audit logging
Simulate a two-phase commit:
Compare transaction throughput:
Implement:
Atomicity: All operations succeed or all fail
-- Either BOTH updates happen, or NEITHER
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;
Consistency: Database always in valid state
-- Balance cannot go negative (constraint maintained)
CHECK (balance >= 0)
Isolation: Transactions don't interfere
-- Transaction A doesn't see Transaction B's uncommitted changes
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Durability: Committed data survives crashes
-- After COMMIT, data is permanent
COMMIT; -- Data now safe even if power fails
| Level | Dirty Read | Non-Repeatable Read | Phantom Read |
|---|---|---|---|
| READ UNCOMMITTED | Possible | Possible | Possible |
| READ COMMITTED | Prevented | Possible | Possible |
| REPEATABLE READ | Prevented | Prevented | Possible |
| SERIALIZABLE | Prevented | Prevented | Prevented |
SQLite Note: Only supports SERIALIZABLE (default)
Cause: Another process has a write lock Solution:
-- Use WAL mode for better concurrency
PRAGMA journal_mode=WAL;
Cause: Circular lock dependency Solution: Implement consistent lock ordering (TODO 3)
Cause: Another transaction modified the row Solution: Retry with fresh data or ask user to resolve
Cause: Port already in use Solution:
# Check what's using the port
lsof -i :5435
# Stop conflicting service or change port in docker-compose.yml
Before considering this activity complete, verify:
You've mastered transactions when you can:
Debugging Steps:
SELECT * FROM transfers to see transaction historypg_locks system viewDiscussion Questions:
TelebortBank Mission: "Banking without race conditions since 2025"
Happy transaction wrangling! ๐ฐ๐