DEV Community

Cover image for Stop Putting dd() Everywhere Debug the Database From the Source Instead
Tahsin Abrar
Tahsin Abrar

Posted on

Stop Putting dd() Everywhere Debug the Database From the Source Instead

Every backend developer has done this at some point.

A request fails.

diagram

Something is not inserting into the database.

And suddenly the codebase turns into this:

dd($request->all());

dd($user);

dd($campaign);

Log::info($query);
Enter fullscreen mode Exit fullscreen mode

You add logs in controllers.

Then services.

Then repositories.

Then queue workers.

Then event listeners.

And after two hours, you are still confused.

Because the real problem is not where you are looking.


The Day I Realized Controller Debugging Wasn’t Enough

A few months ago, a developer on a team I worked with faced a strange issue.

A simple form submission was supposed to:

  • create a user
  • assign a campaign
  • generate a lead
  • push a welcome email into queue
  • write an activity log

Pretty normal workflow.

But randomly, some users were being created without campaign data.

Sometimes the queue job worked.

Sometimes it didn’t.

Sometimes the transaction rolled back silently.

The first reaction?

Start adding logs everywhere.

Inside controllers:

Log::info('Controller hit');
Enter fullscreen mode Exit fullscreen mode

Inside services:

Log::info('Campaign assigned');
Enter fullscreen mode Exit fullscreen mode

Inside queue workers:

Log::info('Email queued');
Enter fullscreen mode Exit fullscreen mode

Inside transactions:

DB::beginTransaction();
Enter fullscreen mode Exit fullscreen mode

The code became a forest of debugging statements.

Still no clear answer.


The Real Problem

Here’s what most developers forget:

No matter how beautiful your architecture is…

No matter whether you use:

  • Laravel
  • Raw PHP
  • Node.js
  • Python
  • Java

At the end of the day, every query goes to one place:

MySQL.

Always.

Your application is just the messenger.

The database sees everything.

That realization changes how you debug systems.


Instead of Guessing, Watch the Database Directly

The moment we enabled MySQL General Query Log, everything became obvious.

We literally watched the queries execute live.

One terminal command showed the full story.

SET GLOBAL general_log = 'ON';
Enter fullscreen mode Exit fullscreen mode

Then:

tail -f /var/lib/mysql/hostname.log
Enter fullscreen mode Exit fullscreen mode

And suddenly we could see:

INSERT INTO users ...
UPDATE campaigns ...
ROLLBACK;
Enter fullscreen mode Exit fullscreen mode

That last line explained everything.

The transaction was rolling back because another process locked a table for a few seconds.

No controller log would have shown the full picture that clearly.


This Is Why Framework-Level Debugging Often Fails

Modern applications are no longer simple.

A single request may involve:

  • queues
  • events
  • transactions
  • scheduled jobs
  • caching
  • background workers
  • third-party APIs

By the time you debug from inside the controller, the actual issue may already be happening somewhere else entirely.

This is why developers sometimes spend hours debugging “application logic” when the real problem is:

  • a deadlock
  • a lock wait
  • a slow query
  • missing index
  • rollback
  • transaction conflict

And MySQL already knows all of this.


The Most Useful MySQL Debugging Tools

Honestly, there are four MySQL features every backend developer should know.

Not just DBAs.

Actual application developers.

Because these tools solve real-world production headaches.


1. General Query Log See Everything

This is the closest thing to “watching the database think.”

Enable it:

SET GLOBAL general_log = 'ON';
Enter fullscreen mode Exit fullscreen mode

Now every query gets logged.

You can literally submit a form and watch the database flow in real time.

This becomes incredibly useful when:

  • one request touches multiple tables
  • transactions fail
  • duplicate queries happen
  • hidden queries execute behind ORM magic

Especially in large Laravel applications where Eloquent sometimes hides too much.


2. Slow Query Log Find Hidden Performance Problems

This one saves applications.

Seriously.

Sometimes developers optimize controllers endlessly while the real problem is one terrible query.

Enable it:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
Enter fullscreen mode Exit fullscreen mode

Now MySQL logs anything slower than one second.

This helps identify:

  • missing indexes
  • N+1 problems
  • huge scans
  • inefficient joins

I once saw a dashboard drop from 12 seconds to under 800ms just because a slow query log exposed a missing index.

The application code itself was completely fine.


3. InnoDB Status Understand Deadlocks & Locks

This command feels like magic the first time you use it.

SHOW ENGINE INNODB STATUS;
Enter fullscreen mode Exit fullscreen mode

If your application ever experiences:

  • hanging requests
  • frozen queues
  • stuck inserts
  • transaction conflicts

This command can immediately reveal:

LATEST DETECTED DEADLOCK
Enter fullscreen mode Exit fullscreen mode

or:

LOCK WAIT
Enter fullscreen mode Exit fullscreen mode

And suddenly the mystery disappears.


4. Audit Tables & Triggers Permanent Visibility

This is where things become enterprise-level.

Sometimes you need permanent tracking.

For example:

  • who changed data
  • when it changed
  • which table changed
  • what action happened

Instead of depending on controller logs forever, you let MySQL automatically track important events.

Using triggers.

Example:

CREATE TRIGGER users_after_insert
AFTER INSERT ON users
FOR EACH ROW
INSERT INTO audit_logs(table_name, action_type)
VALUES ('users', 'INSERT');
Enter fullscreen mode Exit fullscreen mode

Now the database tracks itself.

Clean.

Reliable.

Framework-independent.


One Important Thing Most Developers Ignore

Do not leave general_log permanently enabled in production.

That is a bad idea.

Because:

  • logs become massive
  • storage grows quickly
  • performance can suffer

The smarter workflow is:

Temporary Debugging

SET GLOBAL general_log = 'ON';
Enter fullscreen mode Exit fullscreen mode

Investigate the issue.

Then disable it:

SET GLOBAL general_log = 'OFF';
Enter fullscreen mode Exit fullscreen mode

Top comments (0)