Today I Learned: What Happens When a Database Transaction Is Not Yet Committed?

Today I Learned: What Happens When a Database Transaction Is Not Yet Committed?

M. Zakyuddin Munziri

M. Zakyuddin Munziri

@zakiego

Originally written in Bahasa Indonesia.

Background

Starting from curiosity about how transactions in databases actually work, a question emerged.

If there are users A and B connected to the same database, and A performs a transaction but hasn't finished yet, will B be blocked?

Setup

The database used is PostgreSQL version 16.2.

It was set up on Docker with the following command:

docker run --name transaction_lab -e POSTGRES_PASSWORD=mysecretpassword -d postgres

Then enter the terminal using this command:

docker exec -it transaction_lab psql -U postgres

First Test

This test is to answer whether user B can still perform a SELECT query while user A is running BEGIN TRANSACTION?

The schema that will be executed is:

  1. User A and user B are connected to the Database
  2. User A runs BEGIN TRANSACTION
  3. User A runs UPDATE (not yet committed)
  4. User B runs SELECT
  5. User A runs COMMIT
  6. User B runs SELECT (again)

Here are the results:

Initially, the President's name was "Avatar".

Then user A performs BEGIN TRANSACTION (2) and performs an UPDATE (3) to change the President's name to "Zuko".

During this gap, user B performs a SELECT (4) to check the President's name. It turns out the President's name is still "Avatar"

After user A completes the transaction by running COMMIT (5), when user B runs SELECT (6) again, only then does the President's name change to "Zuko".

So, the conclusion (CMIIW) from this experiment is that when one user performs a TRANSACTION, other users can still perform SELECT queries, but the data they get is the one that hasn't been updated yet, because the main actor hasn't performed COMMIT on their update.

Second Test

If in the first test, user B only performed a read or SELECT, in this test, we will try having both of them perform an UPDATE on the same data.

  1. User A and user B are connected to the Database
  2. User A runs SELECT
  3. User A runs BEGIN TRANSACTION
  4. User A runs UPDATE on id = 1 (not yet committed)
  5. User B runs UPDATE without TRANSACTION on id = 1 as well
  6. User A runs COMMIT
  7. User A runs SELECT (again)

Here are the results:

During the initial check, the President's name was "Avatar". Then user A starts a TRANSACTION (3) and performs an update to change the President's name to "Zuko" (4). However, user A hasn't performed COMMIT yet.

After that, user B comes in and tries to perform an UPDATE to change the President's name to "Katara". (5) What happened? It turns out user B is waiting. They received no response.

When user A performs COMMIT (6), at that very moment the UPDATE performed by user B is executed.

The result is that the President's name becomes "Katara".

So, the conclusion (CMIIW) from this experiment is that when user A performs a TRANSACTION on one row of data, and then user B comes wanting to edit the same data, user B will be blocked. Until when? Until user A completes their transaction. When user A has completed their transaction, then user B's command is executed. Therefore, the final data is the change made by user B.

Closing

This experiment was only conducted out of curiosity. In more complex cases, the results may differ. Lastly, I am not a backend engineer, which is why I tried to learn by conducting this experiment.

More Articles

I Stopped Digging Through Logs

I Stopped Digging Through Logs

Debugging changed when I stopped reading logs manually and started using AI agents to correlate errors across observability data - faster root cause, fewer dead ends.

Speed Was Never the Hard Part in CI CD

Speed Was Never the Hard Part in CI CD

Fast pipelines don't eliminate shipping fear. Confidence comes from safe rollbacks, feature flags, and systems that behave predictably when things go wrong.