5 exercises — slow query logs, EXPLAIN ANALYZE plans, lock contention, connection pool exhaustion, and recognising expensive query patterns.
0 / 14 completed
1 / 14
PostgreSQL's slow query log shows: duration: 4213.221 ms statement: SELECT * FROM orders WHERE customer_id = 8821 AND status = 'pending';
What does this log entry tell you, and what's the first thing to check?
Slow query logs report duration, not row count or connection time — always read the units carefully (milliseconds here, sometimes microseconds).
Diagnosis workflow: 1. Run EXPLAIN ANALYZE on the exact query to see the execution plan 2. Look for Seq Scan (full table scan) on a large table — a strong signal that an index is missing 3. Check existing indexes: \d orders in psql 4. If customer_id and status are frequently filtered together, a composite index (customer_id, status) is usually more effective than two separate single-column indexes
Vocabulary:slow query log — a log of queries exceeding a configured duration threshold (log_min_duration_statement in Postgres). Not every slow query is a bug — some are legitimately expensive reports — but a slow query on a hot path (like an order lookup) needs urgent attention.
2 / 14
EXPLAIN ANALYZE output for a slow query includes this line: Seq Scan on payments (cost=0.00..48291.00 rows=1200000 width=64) (actual time=0.021..892.442 rows=3 loops=1)
How would you describe the problem shown here to a teammate?
Reading an EXPLAIN ANALYZE plan: • Seq Scan — Postgres reads every row in the table sequentially; efficient for scanning most/all of a small table, expensive on large tables with a selective filter • cost=0.00..48291.00 — Postgres's internal cost estimate (startup..total), in arbitrary units, useful for comparing plans, not wall-clock time • rows=1200000 — the planner's estimate of rows this step will produce (from table statistics, not the real count) • actual time=0.021..892.442 — the real measured time in milliseconds (start..end) — this is the number that matters for "is it slow" • rows=3 (in "actual") — only 3 rows actually matched
The tell-tale mismatch: scanning ~1.2 million rows to return 3 means the database had no efficient way to skip to the relevant rows — the fix is almost always adding an index on the columns in the WHERE clause. After adding an index, you'd expect to see Index Scan or Index Only Scan instead of Seq Scan, with dramatically lower actual time.
3 / 14
A MySQL error log shows: [Warning] Aborted connection 48213 to db: 'app_prod' user: 'app_user' host: '10.0.4.12' (Got timeout reading communication packets) ...alongside application logs showing: ERROR: could not obtain lock on row in relation "inventory" — waiting on transaction 88213 held by connection 41
What is happening, described in plain English?
Lock contention vocabulary: • Row lock — a lock held on a specific row by a transaction that has modified it, released on COMMIT or ROLLBACK • Lock wait / blocking — a second transaction trying to modify the same row must wait until the first releases its lock • Deadlock — two transactions each waiting on a lock the other holds; the database detects this and forcibly rolls back one of them (different from simple blocking, which resolves once the holder commits)
Root causes of long lock holds: a transaction left open by application code (e.g. forgotten COMMIT, an exception path that skips cleanup), a transaction that does slow work — like calling an external API — while still holding the lock, or a long-running batch update touching many rows.
Diagnosis: query pg_locks / pg_stat_activity (Postgres) or SHOW ENGINE INNODB STATUS (MySQL) to find which transaction is blocking, how long it has been open, and what statement it's running.
The "Aborted connection" line is a separate, secondary symptom: the client gave up waiting and its connection was dropped by the server after a timeout — a common downstream effect of a long lock wait, not the root cause itself.
4 / 14
You see this in a database's slow query log during a traffic spike: duration: 15002.884 ms statement: SELECT COUNT(*) FROM events WHERE created_at > NOW() - INTERVAL '1 hour'; appearing hundreds of times per minute. How would you summarise the impact of this pattern in an incident channel?
Reading logs "as a sequence" — recognising a pattern, not just a single line — is a core log-reading skill. A single slow query is a curiosity; the same expensive query recurring hundreds of times per minute is a systemic problem.
Why this matters: most databases have a limited connection pool. If each of these queries holds a connection for 15 seconds, the pool fills up quickly, and unrelated (normally fast) queries start queueing behind them — this is how one bad query pattern degrades an entire service, not just the endpoint that issues it.
Communicating impact clearly: in an incident update, name the query pattern, its frequency, its duration, and the likely blast radius ("starving other queries of connections") rather than just "the database is slow" — this gives the team an actionable target (add caching, add an index, rate-limit the endpoint, or add a materialized count) instead of a vague symptom.
Common fixes for this exact pattern: cache the count with a short TTL, maintain a running counter updated incrementally instead of counting on every request, or add an index on created_at if none exists.
5 / 14
A connection pool metrics log shows: {"pool":"primary_db","active":20,"idle":0,"waiting":47,"max":20}
What does this indicate, and what's the correct interpretation?
Connection pool vocabulary: • active — connections currently checked out and in use by a query • idle — connections open but not currently in use, ready to be handed to the next request • waiting — requests that need a connection but none are available, queued • max — the configured upper bound on total connections
active == max and idle == 0 with a large waiting count is the signature of pool exhaustion: every connection is busy, and new requests are stacking up rather than being served.
Root causes to investigate, in order: 1. Are queries taking longer than normal (check slow query log) — connections held longer means fewer available 2. Is there a connection leak — code that checks out a connection and never returns it (missing close()/release() on an error path) 3. Is max simply too low for current traffic
In an incident update: "The database connection pool is exhausted — 47 requests are queued because all 20 connections are busy, likely due to [slow queries / a leak]" is far more actionable than "the app is slow."
6 / 14
During a code review for a new feature that uses the SELECT statement to query user activity logs, you notice the following in the PostgreSQL slow query log:
duration: 12345.67 ms statement: SELECT * FROM user_activity WHERE event_type = 'login' AND timestamp > NOW() - INTERVAL '5 minutes'; Which of the following is the MOST appropriate initial action to suggest to the developer?
The log entry indicates a long duration for a particular query. The most logical first step is to examine potential index issues—a missing or poorly designed index on the user_activity table would likely cause full table scans during this type of query. Suggesting a different SQL dialect or immediately rewriting the query without understanding the root cause is premature and could introduce new problems. Requesting more general load metrics might be useful later, but doesn't address this specific performance bottleneck.
7 / 14
You're investigating a slowdown in a reporting service that relies on querying the orders table. The application logs show frequent attempts to acquire locks on rows with the primary key of order IDs. A Slack message from the DBA reads: 'Looks like we've got a lot of deadlocks.'
What does this situation *most* likely indicate?
Deadlocks are precisely what this Slack message describes—two or more transactions each holding a lock on a resource that another transaction needs. This creates a circular dependency where neither transaction can proceed. While the other options could *contribute* to contention, the core issue is the concurrent access and locking behavior. Addressing deadlocks typically involves identifying and resolving the conflicting code or database design.
8 / 14
During a standup meeting, your team lead asks you to explain why the MySQL error log is showing:
[Error] Connection refused - 1049 - Access denied for user 'web_app'@'localhost' Alongside application logs indicating that the web application is unable to connect to the database.
How would you best explain this issue to your team?
This error message clearly indicates a permissions problem. The user 'web_app'@'localhost' lacks the necessary privileges (e.g., SELECT, INSERT) to access the database. It's highly unlikely that the MySQL server is down or that there's a firewall issue without other symptoms. Incorrect application configuration is possible, but the error message points directly to the user account's lack of authorization.
9 / 14
You are reviewing a pull request that adds a new feature to a system logging service. The CI/CD pipeline generates an API response containing the following log entry:
{ "timestamp": "2024-10-27T10:30:00Z", "level": "INFO", "message": "User X logged in from Y location" } The developer states they're using this log entry to track user activity. What's the MOST important consideration you should raise regarding the long-term use of this log data?
While the API response is useful initially, the unstructured nature (JSON without defined fields) makes it problematic for long-term analysis. Querying becomes difficult and unreliable as time goes on – you'll need to parse the entire JSON string every time. For robust logging, a structured format like JSON with consistent fields is essential.
10 / 14
During a code review of a new microservice, you're examining the logs generated by a query that retrieves recent customer orders. The PostgreSQL slow query log contains this entry:
duration: 9876.54 ms statement: SELECT * FROM orders WHERE order_date BETWEEN '2023-11-15' AND '2023-11-20'
A senior developer comments: 'This query is running slowly, but the numbers look reasonable – it's just filtering by date ranges.' What's your response to this comment, focusing on how you would investigate further?
The key here isn't simply confirming the query *is* slow. The developer's comment misses the crucial point of potential date range inefficiency and the impact on performance. A wide date range often leads to scanning a large portion of the `orders` table, which is a common cause of slow queries. This response highlights the need for more granular investigation into the date range parameters.
11 / 14
You receive this Slack message from a junior developer: 'The database is showing a long duration for a query that's counting active users. It's like 30 seconds! I checked the indexes and they seem fine.'
What would be your immediate follow-up question to help diagnose the problem?
While understanding the SQL statement is important, focusing solely on that without considering resource constraints is premature. High CPU usage during the query's execution strongly suggests that the database server itself might be the bottleneck – perhaps due to heavy load or a lack of resources. This question prompts for a critical observation about the system's overall health.
12 / 14
You're troubleshooting an issue with a service that uses a database to store user preferences. The API endpoint returns this log entry:
{ "timestamp": "2024-10-27T14:45:30Z", "level": "error", "message": "Timeout waiting for lock on table 'user_preferences'", "user": "john.doe", "session_id": "abc123xyz"}
Considering this log entry, what's the *most* likely root cause of the problem?
This log entry specifically indicates a 'Timeout waiting for lock'. This almost always means another process (another query or transaction) already holds an exclusive lock on the `user_preferences` table. Concurrency issues are incredibly common in database interactions and this response directly addresses that.
13 / 14
During your daily stand-up meeting, a team member says: 'I'm seeing a lot of slow queries in the logs – mostly SELECT statements pulling data from our customer order database.'
How would you frame this issue to the rest of the team for discussion?
This situation requires a measured response. Simply stating 'optimize SQL' is too vague. The correct approach involves acknowledging the problem, indicating you are investigating *why* it's slow (understanding the queries), and recognizing that optimization might not be the immediate solution – it could be caused by other factors like concurrency or schema design.
14 / 14
You're reviewing a pull request to add a new feature that generates daily reports. The PR description includes this sentence: 'The query now uses an index on the `orders` table to speed up retrieval of order data.'
What's your immediate concern regarding this statement, and what additional information would you seek before approving the change?
While indexing *can* improve performance, it doesn't guarantee that the index is being utilized. It's crucial to verify this by examining the query execution plan. The database optimizer might choose a different execution path (e.g., a full table scan) if it deems it more efficient, even with an available index. This question highlights the importance of verifying assumptions about database behavior.
What will I practise in "Database Query Logs — Log Reading Exercises"?
Practice reading slow query logs, EXPLAIN ANALYZE output, lock contention errors, and connection pool exhaustion. Diagnose PostgreSQL and MySQL performance problems. 5 exercises for backend developers.
How many exercises are in this module?
This module has 14 multiple-choice exercises, each with instant feedback and a full explanation of the correct answer.
Is this exercise free to use?
Yes. Every exercise on CoderSlingo, including this one, is free to use with no account, sign-up, or paywall.
Do I need to create an account to do these exercises?
No account is required. Just click an option to answer — your score for this session is tracked automatically in the progress bar above.
What happens if I choose the wrong answer?
You'll immediately see which answer was correct, plus a full explanation covering the vocabulary and reasoning behind it — mistakes are where most of the learning happens.
Can I retry the exercises if I want a higher score?
Yes — use the "Try again" button on the results screen to reset and go through all the questions again.
Is my progress saved if I close the page?
No. Progress is tracked only for your current visit; reloading or leaving the page resets the counter. This keeps the exercise simple and account-free.
Where can I find more Log Reading exercises?
Browse the full Log Reading hub for related drills, or check the "Next up" link below to continue with a connected topic.
How is this different from reading an article on the same topic?
Articles explain vocabulary and concepts in prose; this exercise tests and reinforces that vocabulary through active recall with immediate feedback — the two work best together.
Who writes these exercises?
Every exercise is written by the CoderSlingo team, drawing on real workplace English used in IT roles, then reviewed for accuracy and clarity.