27/11/2025

Introduction to SQL Server Transactions (Transaction Isolation Part 4)

This is forth part of "Introduction to SQL Server Transaction" series. You can see previous sections below:

Part 1

Part 2

Part 3

In this part we discuss two SQL Server isolation levels in deep.


Read Uncommitted – The “Wild West” of Isolation

Read Uncommitted is the lowest isolation level. It allows dirty reads, non-repeatable reads, and phantoms – basically all issues relate to concurrency can be seen in this isolation level. No locks are taken on reads, so you can read uncommitted changes. 

We can set the isolation level to Read Uncommitted on SQL Server using statement like below:


SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;


Also in query level we can use query hint (NOLOCK) to force Read Uncommitted isolation level.


Example: Dirty-read scenario. A pending payment transaction withdraws $45 from Betty’s $78 balance, then rolls back. Meanwhile an ATM transaction (right) reads the balance as $33. The ATM saw a dirty value that never became final.


Demonstration:


-- Session A: Begin a transaction and update, but do not commit immediately.

BEGIN TRAN;


SELECT Balance FROM BankAccount WHERE AccountNumber = 'Betty'

-- This return $78


UPDATE BankAccount

SET Balance = Balance - 45

WHERE AccountNumber = 'Betty';


-- Wait or do other work before committing/rolling back...

WAITFOR DELAY '00:00:10';  

ROLLBACK;  



-- Session B (simulated concurrently): Read without locking

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT Balance FROM BankAccount WHERE AccountNumber = 'Betty';

SELECT in Session B will return 33 (assuming you have run the Session B within 10 second delay in Session A). But real balance is 78.

Under Read Uncommitted, SQL Server does not issue any shared locks on reads, so a select can return “dirty” changes from another transaction. The only advantage is maximum concurrency (no waiting), but at the cost of consistency: all anomalies can happen.


Read Committed – Default Safe Reads

Read Committed is the SQL Server default isolation level (when no explicit level is set). It prevents dirty reads: you will never see another transaction’s uncommitted changes. However, it still allows non-repeatable reads and phantoms (unless you enable row-versioning, more about this in later blog posts). 

In locking mode (SQL Server’s default), a read places shared locks that last only for the duration of each statement. If another transaction has an exclusive lock on a row, your SELECT will wait until that transaction commits or rolls back. Thus, Read Committed “protects” your reads from dirty data.


-- Session A: Start and update a row, but hold it.

BEGIN TRAN;

UPDATE BankAccount

SET Balance = Balance - 45

WHERE AccountNumber = 'Betty';


-- (Session A, not yet committed), carrying out other statement execution



-- Session B: Default Read Committed SELECT

SELECT Balance FROM BankAccount WHERE AccountNumber = 'Betty';

-- Session B will *wait* here until Session A commits or rolls back.


As you can see above, session B waits, in executing query mode (no results).

-- If Session A commits, B then sees the new balance (i.e. 33) ; if A rolls back, B sees the old balance (i.e. 78).

COMMIT;  -- Session A eventually commits or rollbacks

This will be the result in Session B:



In above demonstration, SQL server used row level exclusive lock in Session A. Then because of the default isolation level (i.e. Read committed), Session B has used shared lock. However, since "Betty's" row is exclusively locked by Session A, Session B couldn't get the shared lock on the row. Therefore, Session B (select) had to wait till Session A committed or rollback the transaction.

Since Session B had to wait, till Session A finishes, there were no dirty reads (didn't see the temporary balance of 33). But as you can see, we now have locking (i.e. Session B waiting) scenario. This is why you should handle isolation levels very carefully.

Furthermore, data can be changed by other transactions between individual statements… resulting in nonrepeatable reads or phantom data”. In other words, each SELECT in your transaction sees only committed data at that moment, but different SELECTs in the same transaction might see different results if other transactions commit in between.



19/11/2025

BMAD Method - Part 1

Let me start by saying I'm not into Vibe coding. Mainly because I know one or two about coding and there fore I see far Vibe coding can go. But I'm not against people who do Vibe coding. It has given more people, rather than traditional programmers to develop their ideas in very short time, very cost effective way. Also Vibe coding is a tool when it comes to do rapid prototyping. Even well established software companies can use Vibe coding for producing demo software. So it is not something to ignore.

I can see Vibe Coding is now evolving, through context engineering. One of the interesting AI assisted coding method which evolved like that is BMAD method

BMAD - Breakthrough Method for Agile AI Driven Development.

Because it follows Agile principals of software development, this method has caught my attention. You can find more details about this method in above listed link.

There are many ways you can use this method. In fact, you can even use this method to analyze your life problems. But I'm more interested in using this in software development. There fore I started using this in VS Code through GitHub Copilot. Following describe how I started.

Before you installing BMAD framework, you need Node.js v20 or above.

Step 1: Install

Go to root of your development folder via terminal (command prompt). E.g. D:\Dev

Execute following

npx bmad-method install


You will see a screen similar to above. This will change as this framework get upgraded. Currently we are in version 4.44.3, but near the inevitable upgrade of version 6.

Step 2: Create project folder

Enter the path for the project. If it doesn't exist bmad installer will create it.

Step 3: Select what framework to install


There are few options to choose from, couple of them relate to game development. But for our purpose we use default "BMad Agile Core System". If you not sure choose this one and continue.

It will ask couple of questions regarding sharding of PRD and architect files. I will choose yes, because most of time these files are huge and having them separated to multiple file in logical points makes it easy for us to refer to them.

Step 4: Selecting IDE


I will be based on VSCode and GitHub Copilot.

It will ask following question:

* How would you like to configure GitHub Copilot settings?

Choose the default to make the process fast. Or choose manual if you want much tighter control.

* To install web bundles.

I will choose no to this. Because you can do the same thing you do with web bundles in IDE.

That's all.

Step 5: Then launch VSCode

You will see something like below when open the project


Step 6: Start Agent

Open Github Copilot Chat in Agent mode and then type:

*workflow-init

This will start BMad method in agent mode with following options:


If it is branch new project, I will start with item 1.



Installing SQL Server 2025

Microsoft has recently release SQL Server 2025. So it is my time to get it hands on. One of the thing they highlight in this release is AI r...