LOCAL RUNBOOK / 15–25 MIN
Make the evidence yours.
Use two real sessions and an observer on your own machine. The companion repository is public because changing SQL and debugging concurrency are part of this learning workflow.
01 / Prepare an isolated runtime
Requirements: Python 3.11+, Docker Engine and Compose v2 or standalone docker-compose. Reserve two CPU cores, 2 GiB available engine memory and at least 2 GiB free disk. The database container is capped at 2 CPUs / 1 GiB. No paid services are needed.
Use an existing healthy engine, or create a dedicated Colima profile on macOS. Never clean unrelated volumes to make space. If using the profile below, retain DOCKER_CONTEXT for every Lab command.
colima start --profile mysql-lab --cpu 2 --memory 2 --disk 12 --activate=false
export DOCKER_CONTEXT=colima-mysql-lab02 / Start, run and stop
git clone https://github.com/lynnlee1229/mysql-lab.git
cd mysql-lab
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python lab.py doctor
python lab.py start --port 13316
python lab.py run
python lab.py stopstart generates random passwords in ignored .local/ with restricted file permissions, creates only the lynn-mysql-lab Compose project and binds 127.0.0.1:13316. Choose a free port on first start. Do not connect this runner to an existing business database: run deliberately drops and rebuilds its own mysql_lab tables.
A successful run writes a timestamped sanitized run.json under .local/runs/. The full raw InnoDB deadlock text is in raw-local-only/ and is never copied to the website. Failed runs exit nonzero and do not produce a success report.
03 / Predict, inspect, change
- Predict which second UPDATE waits. Find the observer barrier, the real data_lock_waits edge, error 1213 and the two final values. Compare the ordered control.
- Predict four read values under each isolation level. Inspect plain reads before and after FOR UPDATE. Check that B’s later writer actually waits.
- Compare full scan versus indexed noncovering SQL with identical hashes. Compare covering range versus DATE_FORMAT using identical projection and hashes. Read actual rows in EXPLAIN ANALYZE before interpreting timings.
Modify scripts/experiments.py only after preserving a baseline report. Change the locking order or query predicate, rerun, and compare actual evidence. Fixed seeds preserve the data; optimizer and hardware behavior can still differ.
04 / Preserve or explicitly destroy
python lab.py stop # retains the named data volume
python lab.py start # uses the same credentials and volume
python lab.py run # resets only the synthetic experiment tables
# Explicitly destructive: removes only this Lab project and data volume
python lab.py destroy --confirm lynn-mysql-labDo not delete .local/config.json or compose.env while retaining the database volume: its persisted passwords must match. stop does not stop your Docker engine. With a dedicated profile, stop this Lab first, then optionally run colima stop --profile mysql-lab.
05 / Build the reading site and verify
python -m unittest discover -s tests -v
python scripts/validate.py records/run-clean.json records/run-repeat.json
python scripts/build_site.py
python scripts/check_site.py
python -m http.server 18911 --bind 127.0.0.1 --directory distOpen http://127.0.0.1:18911/mysql-lab/en/. The exporter reads only committed allowlisted records and site assets. It never scans .local/, raw logs, environment files or the homepage source.
Pinned image and troubleshooting
mysql:8.4.13@sha256:a81d043930e51745522bd5c430961cf8286f0a23f0a9a2a6e0108f7ea71b0902doctor reports missing engine, Compose, driver or disk space. start fails visibly on occupied ports or initialization failure. Connection refusal: check the selected context and start. Error 1205: inspect the saved timeout case. Assertion failure: retain local evidence and rerun after stop/start; do not substitute expected values.