SlideShare a Scribd company logo
Slides & scripts: BrentOzar.com/sql/deadlocks/
Deadlocks
Let’s do one, understand it, and fix it.
Slides & scripts: BrentOzar.com/sql/deadlocks/
99-05: dev, architect, DBA
05-08: DBA, VM, SAN admin
08-10: MCM, Quest Software
Since: consulting DBA
www.BrentOzar.com
Help@BrentOzar.com
Slides & scripts: BrentOzar.com/sql/deadlocks/
Session agenda
Basics:
• 3 concurrency issues
• 3 ways to fix ‘em all
• 1 “fix” that makes things worse: NOLOCK
One real fix: work on tables in a consistent order
• Demo: unrealistic query
• Demo: realistic query
Using sp_BlitzLock to find the queries you need to
fix
Slides & scripts: BrentOzar.com/sql/deadlocks/
Concurrency challenges
Locking: Lefty takes out a lock.
Blocking: Righty wants a lock, but Lefty already has it.
SQL Server will let Righty wait for forever,
and the symptom is LCK* waits.
Deadlocks:
Lefty has locks, then wants some held by Righty.
Righty has locks, then wants some held by Lefty.
SQL Server solves this one by killing somebody,
and the symptom is dead bodies everywhere.
Slides & scripts: BrentOzar.com/sql/deadlocks/
3 ways to fix concurrency issues
1. Have enough indexes to make your queries fast,
but not so many that they slow down DUIs,
making them hold more locks for longer times.
(I cover this in Mastering Index Tuning.)
2. Tune your transactional code.
(This module focuses on this topic.)
3. Use the right isolation level for your app’s needs.
(I cover this in Mastering Server Tuning.)
Slides & scripts: BrentOzar.com/sql/deadlocks/
1 way doesn’t fix it: dirty reads
WITH (NOLOCK):
• Ignores other people’s row locks
• Still takes out schema stability locks
(and honors other peoples’ schema locks)
SET TRANSACTION ISOLATION LEVEL READ
UNCOMMITTED
• Like putting WITH (NOLOCK) on every table
Slides & scripts: BrentOzar.com/sql/deadlocks/
Because with dirty reads…
1. You can see data that was never committed
2. You can see rows twice
3. You can skip rows altogether
4. Your query can fail with an error:
Could not continue scan with NOLOCK due to data movement
Slides & scripts: BrentOzar.com/sql/deadlocks/
Demoing it
If I count the number of Alexes,
and I use NOLOCK,
I get the same result every time.
As long as nothing is happening.
Slides & scripts: BrentOzar.com/sql/deadlocks/
But while it runs…
Let’s update everyone who ISN’T Alex:
Note that I am NOT inserting or deleting rows.
Just updating the non-Alexes.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Run them both at the same
time:
Slides & scripts: BrentOzar.com/sql/deadlocks/
That’s NOLOCK.
And that’s not a bug.
That’s what it’s
designed to do.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Sometimes, these are OK.
1. You can see data that was never committed
2. You can see rows twice
3. You can skip rows altogether
4. Your query can fail with an error:
Could not continue scan with NOLOCK due to data movement
But when they’re not OK, we have some fixes to
do.
Slides & scripts: BrentOzar.com/sql/deadlocks/
3 ways to fix concurrency issues
1. Have enough indexes to make your queries fast,
but not so many that they slow down DUIs,
making them hold more locks for longer times.
(I cover this in Mastering Index Tuning.)
2. Tune your transactional code.
(This module explores this topic.)
3. Use the right isolation level for your app’s needs.
(I cover this in Mastering Server Tuning.)
Slides & scripts: BrentOzar.com/sql/deadlocks/
Session agenda
Basics:
• 3 concurrency issues
• 3 ways to fix ‘em all
• 1 “fix” that makes things worse: NOLOCK
One real fix: work on tables in a consistent order
• Demo: unrealistic query
• Demo: realistic query
Using sp_BlitzLock to find the queries you need to
fix
Slides & scripts: BrentOzar.com/sql/deadlocks/
Start SSMS with two windows.
Use Lefty.sql and Righty.sql from your resources.
In Lefty, create & populate the tables.
Slides & scripts: BrentOzar.com/sql/deadlocks/
In Lefty, start a transaction.
Begin tran, update dbo.Lefty, but don’t commit.
The left window is now locking dbo.Lefty.
Slides & scripts: BrentOzar.com/sql/deadlocks/
In Righty, start another.
Begin tran, update dbo.Righty, but don’t commit.
The right window is now locking dbo.Righty.
Slides & scripts: BrentOzar.com/sql/deadlocks/
The situation so far:
Left window has:
• dbo.Lefty
exclusive lock
Right window
has:
• dbo.Righty
exclusive lock
Slides & scripts: BrentOzar.com/sql/deadlocks/
In Lefty, update dbo.Righty.
The update starts running, but is blocked, and sits
there waiting for dbo.Righty to commit or roll back.
Slides & scripts: BrentOzar.com/sql/deadlocks/
The situation so far:
Left window has:
• dbo.Lefty
exclusive lock
• Wants a lock
on dbo.Righty,
but can’t get it
(yet)
Right window
has:
• dbo.Righty
exclusive lock
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
The situation so far:
Left window has:
• dbo.Lefty
exclusive lock
• Wants a lock
on dbo.Righty,
but can’t get it
(yet)
Right window
has:
• dbo.Righty
exclusive lock
Slides & scripts: BrentOzar.com/sql/deadlocks/
But let’s do something terrible.
In the right hand window, don’t commit or roll
back: instead, try to get a lock on dbo.Lefty.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Things are going to happen fast.
I’ll describe what’s going to happen before I hit F5:
• The right window will want to run, but…
Slides & scripts: BrentOzar.com/sql/deadlocks/
The situation will become:
Left window has:
• dbo.Lefty
exclusive lock
• Wants a lock on
dbo.Righty, but
can’t get it
(ever)
Right window has:
• dbo.Righty
exclusive lock
• Wants a lock on
dbo.Lefty, but
can’t get it
(ever)
Slides & scripts: BrentOzar.com/sql/deadlocks/
Things are going to happen fast.
I’ll describe what’s going to happen before I hit F5:
• The right window will want to run, but…
• Neither side will be able to make progress
• SQL Server’s deadlock monitor wakes up every 5
seconds, and when he does, he’ll see the
problem
• He’ll pick the query that’s the easiest to roll back,
and kill it
Slides & scripts: BrentOzar.com/sql/deadlocks/
I hit F5 in the right window,
and…
Within 5 seconds, SQL Server kills one.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
The root cause: bad ordering
Left window has:
• dbo.Lefty
exclusive lock
• Wants a lock on
dbo.Righty, but
can’t get it
(ever)
Right window has:
• dbo.Righty
exclusive lock
• Wants a lock on
dbo.Lefty, but
can’t get it
(ever)
Slides & scripts: BrentOzar.com/sql/deadlocks/
The fix: better ordering
If we work on tables in a consistent order:
• Always update dbo.Lefty first,
then update dbo.Righty
Or:
• Always update dbo.Righty first,
then update dbo.Lefty
We’ll be fine either way, as long as we’re
consistent.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Trying it:
I set up both windows to work on dbo.Lefty first.
I hit execute in the left window first, then the right:
Slides & scripts: BrentOzar.com/sql/deadlocks/
This sounds bad at first.
We have a new problem: blocking.
The right window can’t make progress.
But that’s actually good:
he can’t grab a lock that would block others.
The left side is able to keep right on going.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Continuing in the left window…
Slides & scripts: BrentOzar.com/sql/deadlocks/
Continuing in the left window…
When the left finally commits, the right is free to
start making progress, and can’t be blocked by the
left.
Slides & scripts: BrentOzar.com/sql/deadlocks/
The moral of the story
Work in tables in a consistent order, like:
• Always parents, then children
• Or always children, then parents
Which one you choose is less important
than being ruthlessly consistent.
If even one query works out of order,
there will be deadlocks.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Session agenda
Basics:
• 3 concurrency issues
• 3 ways to fix ‘em all
• 1 “fix” that makes things worse: NOLOCK
One real fix: work on tables in a consistent order
• Demo: unrealistic query
• Demo: realistic query
Using sp_BlitzLock to find the queries you need to
fix
We are here.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Real-world scenario
At Stack Overflow, you can up/downvote questions.
Voting
Slides & scripts: BrentOzar.com/sql/deadlocks/
What happens when you vote
Update your Users.LastAccessDate column to show
that you’ve been accessing the site
Insert a row in the Votes table
Add one point to the question’s score
(by updating its row in Posts (Q&A))
Add one point to the question-asker’s reputation
(by updating their row in Users, set Reputation +
1)
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
How it goes wrong
What if these two happen at the exact same time:
User A upvotes a question
owned by UserB
UserB upvotes a question
owned by UserA
Slides & scripts: BrentOzar.com/sql/deadlocks/
Just for this demo
Slides & scripts: BrentOzar.com/sql/deadlocks/
Start these two at the same time
And one will always lose. (Which one? Tough to
tell.)
Slides & scripts: BrentOzar.com/sql/deadlocks/
First, we lock our own row
Last, we try to lock someone
else’s
Slides & scripts: BrentOzar.com/sql/deadlocks/
Will ordering help?
What if we move all the user updates to the top?
Just for this demo
Slides & scripts: BrentOzar.com/sql/deadlocks/
Still screwed.
It’s not enough to lock tables in the same order:
we also need to touch them as few times as
practical.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Could we update both users at once?
How might we solve this problem?
Slides & scripts: BrentOzar.com/sql/deadlocks/
Ways to fix it
“Just remove the waitfor” = “make it all faster”
• Get faster hardware
• Tune indexes on the underlying tables
• Don’t hold transactions open on the app side
Try merging both Users updates into a single query
(where it’s the Voter, OR it’s the question-owner)
Do the LastAccessDate update outside of the
transaction (does it really matter?)
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
It works though! No deadlocks.
Well, kinda: there’s a catch. Notice the runtimes.
Slides & scripts: BrentOzar.com/sql/deadlocks/
The longer it takes before others can start
work.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Another
approach
Do we really need
your Last Access
Date to be part of
the transaction?
Slides & scripts: BrentOzar.com/sql/deadlocks/
Run ‘em both at the same time…
No deadlocks, AND they both finish in 10 seconds!
Slides & scripts: BrentOzar.com/sql/deadlocks/
The more you fix, the faster it
goes
“Just remove the waitfor” = “make it all faster”
• Get faster hardware
• Tune indexes on the underlying tables
• Don’t hold transactions open on the app side
Try merging both Users updates into a single query
(where it’s the Voter, OR it’s the question-owner)
Do the LastAccessDate update outside of the
transaction (does it really matter?)
Slides & scripts: BrentOzar.com/sql/deadlocks/
Session agenda
Basics:
• 3 concurrency issues
• 3 ways to fix ‘em all
• 1 “fix” that makes things worse: NOLOCK
One real fix: work on tables in a consistent order
• Demo: unrealistic query
• Demo: realistic query
Using sp_BlitzLock to find the queries you need to
fix
Slides & scripts: BrentOzar.com/sql/deadlocks/
sp_BlitzLock helps you spot ‘em.
Thanks to SQL 2012 or newer, the default system
health Extended Events session, and Erik Darling:
Slides & scripts: BrentOzar.com/sql/deadlocks/
Top result set: list of deadlocks
Scroll to the far right, and you also get the
deadlock graph. Save it as an XDL file, then re-
open it in SSMS or in SentryOne Plan Explorer.
Slides & scripts: BrentOzar.com/sql/deadlocks/
Bottom results: analytics
This is what really helps me get to the bottom of it:
Slides & scripts: BrentOzar.com/sql/deadlocks/
Bottom results: analytics
Tables & indexes: use my D.E.A.T.H. Method on
‘em
Queries: hit tables in a consistent order, tune txns
Slides & scripts: BrentOzar.com/sql/deadlocks/
Slides & scripts: BrentOzar.com/sql/deadlocks/
3 ways to fix concurrency issues
1. Have enough indexes to make your queries fast,
but not so many that they slow down DUIs,
making them hold more locks for longer times.
(I cover this in Mastering Index Tuning.)
2. Tune your transactional code.
(This module focuses on this topic.)
3. Use the right isolation level for your app’s needs.
(I cover this in Mastering Server Tuning.)

More Related Content

PPTX
AGILE Model (SDLC).pptx
PDF
Penetration Testing SAP Systems
PDF
Zachman Enterprise Security Architecture
PPTX
Time management
PDF
Process Automation Forum April 2021 - Practical Process Automation
PDF
Legacy systems modernisation
PPTX
Types of cloud computing
PPT
Time Management PowerPoint PPT Content Modern Sample
AGILE Model (SDLC).pptx
Penetration Testing SAP Systems
Zachman Enterprise Security Architecture
Time management
Process Automation Forum April 2021 - Practical Process Automation
Legacy systems modernisation
Types of cloud computing
Time Management PowerPoint PPT Content Modern Sample

What's hot (7)

ODP
PPTX
Cross Data Center Replication with Redis using Redis Enterprise
PDF
Microservices architecture overview v3
PDF
The Business Case for Robotic Process Automation (RPA)
PDF
Low Code Capabilities of Digital Product Design Platforms
PPT
RAID and LVM
PDF
Effective time management strategies ( pdf drive )
Cross Data Center Replication with Redis using Redis Enterprise
Microservices architecture overview v3
The Business Case for Robotic Process Automation (RPA)
Low Code Capabilities of Digital Product Design Platforms
RAID and LVM
Effective time management strategies ( pdf drive )
Ad

Similar to Deadlocks: Lets Do One, Understand It, and Fix It (20)

PPTX
Welcome to the nightmare of locking, blocking and isolation levels!
PDF
Headaches of Blocking, Locking, and Deadlocking
PPTX
The Nightmare of Locking, Blocking and Isolation Levels!
PPTX
DBA vs Deadlock: How to Out-Index a Deadly Blocking Scenario
PPTX
The nightmare of locking, blocking and isolation levels!
PPT
Troubleshooting Deadlocks in SQL Server 2000
PPTX
Welcome to the nightmare of locking, blocking and isolation levels!
PPTX
The Nightmare of Locking, Blocking and Isolation Levels!
PDF
The nightmare of locking, blocking and isolation levels!
PDF
The nightmare of locking, blocking and isolation levels
PDF
The Nightmare of Locking, Blocking and Isolation Levels!
PPTX
The Nightmare of Locking, Blocking and Isolation Levels!
PPTX
The Nightmare of Locking, Blocking and Isolation Levels!
PPTX
Deadlock in database
PPTX
Deadlock dbms
PPTX
Geek Sync | How to Detect, Analyze, and Minimize SQL Server Blocking and Locking
PPT
Lecture 5 Deadlocks in Database Systems.ppt
PPT
Locking unit 1 topic 3
PDF
The nightmare of locking, blocking and isolation levels
PPTX
The nightmare of locking, blocking and deadlocking. SQLSaturday #257, Verona
Welcome to the nightmare of locking, blocking and isolation levels!
Headaches of Blocking, Locking, and Deadlocking
The Nightmare of Locking, Blocking and Isolation Levels!
DBA vs Deadlock: How to Out-Index a Deadly Blocking Scenario
The nightmare of locking, blocking and isolation levels!
Troubleshooting Deadlocks in SQL Server 2000
Welcome to the nightmare of locking, blocking and isolation levels!
The Nightmare of Locking, Blocking and Isolation Levels!
The nightmare of locking, blocking and isolation levels!
The nightmare of locking, blocking and isolation levels
The Nightmare of Locking, Blocking and Isolation Levels!
The Nightmare of Locking, Blocking and Isolation Levels!
The Nightmare of Locking, Blocking and Isolation Levels!
Deadlock in database
Deadlock dbms
Geek Sync | How to Detect, Analyze, and Minimize SQL Server Blocking and Locking
Lecture 5 Deadlocks in Database Systems.ppt
Locking unit 1 topic 3
The nightmare of locking, blocking and isolation levels
The nightmare of locking, blocking and deadlocking. SQLSaturday #257, Verona
Ad

More from Brent Ozar (16)

PDF
Fundamentals of TempDB
PDF
Fundamentals of Columnstore - Introductions
PPTX
Top 10 Developer Mistakes That Won't Scale with SQL Server
PPTX
Help! SQL Server 2008 is Still Here!
PPTX
An Introduction to GitHub for DBAs - Brent Ozar
PPTX
How to Think Like the SQL Server Engine
PPTX
SQL Query Optimization: Why Is It So Hard to Get Right?
PPTX
Dynamic SQL: How to Build Fast Multi-Parameter Stored Procedures
PPTX
"But It Worked In Development!" - 3 Hard SQL Server Problems
PPTX
Columnstore Customer Stories 2016 by Sunil Agarwal
PPTX
500-Level Guide to Career Internals
PPTX
Introduction to SQL Server Internals: How to Think Like the Engine
PPTX
Building a Fast, Reliable SQL Server for kCura Relativity
PPTX
How to Make SQL Server Go Faster
PPTX
500-Level Guide to Career Internals
PPTX
What I Learned About SQL Server at Ignite 2015
Fundamentals of TempDB
Fundamentals of Columnstore - Introductions
Top 10 Developer Mistakes That Won't Scale with SQL Server
Help! SQL Server 2008 is Still Here!
An Introduction to GitHub for DBAs - Brent Ozar
How to Think Like the SQL Server Engine
SQL Query Optimization: Why Is It So Hard to Get Right?
Dynamic SQL: How to Build Fast Multi-Parameter Stored Procedures
"But It Worked In Development!" - 3 Hard SQL Server Problems
Columnstore Customer Stories 2016 by Sunil Agarwal
500-Level Guide to Career Internals
Introduction to SQL Server Internals: How to Think Like the Engine
Building a Fast, Reliable SQL Server for kCura Relativity
How to Make SQL Server Go Faster
500-Level Guide to Career Internals
What I Learned About SQL Server at Ignite 2015

Recently uploaded (20)

PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
WOOl fibre morphology and structure.pdf for textiles
PPTX
O2C Customer Invoices to Receipt V15A.pptx
PDF
Hindi spoken digit analysis for native and non-native speakers
PPTX
1. Introduction to Computer Programming.pptx
PDF
DP Operators-handbook-extract for the Mautical Institute
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
Getting started with AI Agents and Multi-Agent Systems
PDF
2021 HotChips TSMC Packaging Technologies for Chiplets and 3D_0819 publish_pu...
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
PPTX
Modernising the Digital Integration Hub
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
STKI Israel Market Study 2025 version august
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
A comparative study of natural language inference in Swahili using monolingua...
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
Programs and apps: productivity, graphics, security and other tools
A novel scalable deep ensemble learning framework for big data classification...
Enhancing emotion recognition model for a student engagement use case through...
WOOl fibre morphology and structure.pdf for textiles
O2C Customer Invoices to Receipt V15A.pptx
Hindi spoken digit analysis for native and non-native speakers
1. Introduction to Computer Programming.pptx
DP Operators-handbook-extract for the Mautical Institute
Group 1 Presentation -Planning and Decision Making .pptx
Getting started with AI Agents and Multi-Agent Systems
2021 HotChips TSMC Packaging Technologies for Chiplets and 3D_0819 publish_pu...
A contest of sentiment analysis: k-nearest neighbor versus neural network
Modernising the Digital Integration Hub
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
STKI Israel Market Study 2025 version august
Univ-Connecticut-ChatGPT-Presentaion.pdf
Zenith AI: Advanced Artificial Intelligence
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
A comparative study of natural language inference in Swahili using monolingua...

Deadlocks: Lets Do One, Understand It, and Fix It

  • 1. Slides & scripts: BrentOzar.com/sql/deadlocks/ Deadlocks Let’s do one, understand it, and fix it.
  • 2. Slides & scripts: BrentOzar.com/sql/deadlocks/ 99-05: dev, architect, DBA 05-08: DBA, VM, SAN admin 08-10: MCM, Quest Software Since: consulting DBA www.BrentOzar.com Help@BrentOzar.com
  • 3. Slides & scripts: BrentOzar.com/sql/deadlocks/ Session agenda Basics: • 3 concurrency issues • 3 ways to fix ‘em all • 1 “fix” that makes things worse: NOLOCK One real fix: work on tables in a consistent order • Demo: unrealistic query • Demo: realistic query Using sp_BlitzLock to find the queries you need to fix
  • 4. Slides & scripts: BrentOzar.com/sql/deadlocks/ Concurrency challenges Locking: Lefty takes out a lock. Blocking: Righty wants a lock, but Lefty already has it. SQL Server will let Righty wait for forever, and the symptom is LCK* waits. Deadlocks: Lefty has locks, then wants some held by Righty. Righty has locks, then wants some held by Lefty. SQL Server solves this one by killing somebody, and the symptom is dead bodies everywhere.
  • 5. Slides & scripts: BrentOzar.com/sql/deadlocks/ 3 ways to fix concurrency issues 1. Have enough indexes to make your queries fast, but not so many that they slow down DUIs, making them hold more locks for longer times. (I cover this in Mastering Index Tuning.) 2. Tune your transactional code. (This module focuses on this topic.) 3. Use the right isolation level for your app’s needs. (I cover this in Mastering Server Tuning.)
  • 6. Slides & scripts: BrentOzar.com/sql/deadlocks/ 1 way doesn’t fix it: dirty reads WITH (NOLOCK): • Ignores other people’s row locks • Still takes out schema stability locks (and honors other peoples’ schema locks) SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED • Like putting WITH (NOLOCK) on every table
  • 7. Slides & scripts: BrentOzar.com/sql/deadlocks/ Because with dirty reads… 1. You can see data that was never committed 2. You can see rows twice 3. You can skip rows altogether 4. Your query can fail with an error: Could not continue scan with NOLOCK due to data movement
  • 8. Slides & scripts: BrentOzar.com/sql/deadlocks/ Demoing it If I count the number of Alexes, and I use NOLOCK, I get the same result every time. As long as nothing is happening.
  • 9. Slides & scripts: BrentOzar.com/sql/deadlocks/ But while it runs… Let’s update everyone who ISN’T Alex: Note that I am NOT inserting or deleting rows. Just updating the non-Alexes.
  • 10. Slides & scripts: BrentOzar.com/sql/deadlocks/ Run them both at the same time:
  • 11. Slides & scripts: BrentOzar.com/sql/deadlocks/ That’s NOLOCK. And that’s not a bug. That’s what it’s designed to do.
  • 12. Slides & scripts: BrentOzar.com/sql/deadlocks/ Sometimes, these are OK. 1. You can see data that was never committed 2. You can see rows twice 3. You can skip rows altogether 4. Your query can fail with an error: Could not continue scan with NOLOCK due to data movement But when they’re not OK, we have some fixes to do.
  • 13. Slides & scripts: BrentOzar.com/sql/deadlocks/ 3 ways to fix concurrency issues 1. Have enough indexes to make your queries fast, but not so many that they slow down DUIs, making them hold more locks for longer times. (I cover this in Mastering Index Tuning.) 2. Tune your transactional code. (This module explores this topic.) 3. Use the right isolation level for your app’s needs. (I cover this in Mastering Server Tuning.)
  • 14. Slides & scripts: BrentOzar.com/sql/deadlocks/ Session agenda Basics: • 3 concurrency issues • 3 ways to fix ‘em all • 1 “fix” that makes things worse: NOLOCK One real fix: work on tables in a consistent order • Demo: unrealistic query • Demo: realistic query Using sp_BlitzLock to find the queries you need to fix
  • 15. Slides & scripts: BrentOzar.com/sql/deadlocks/ Start SSMS with two windows. Use Lefty.sql and Righty.sql from your resources. In Lefty, create & populate the tables.
  • 16. Slides & scripts: BrentOzar.com/sql/deadlocks/ In Lefty, start a transaction. Begin tran, update dbo.Lefty, but don’t commit. The left window is now locking dbo.Lefty.
  • 17. Slides & scripts: BrentOzar.com/sql/deadlocks/ In Righty, start another. Begin tran, update dbo.Righty, but don’t commit. The right window is now locking dbo.Righty.
  • 18. Slides & scripts: BrentOzar.com/sql/deadlocks/ The situation so far: Left window has: • dbo.Lefty exclusive lock Right window has: • dbo.Righty exclusive lock
  • 19. Slides & scripts: BrentOzar.com/sql/deadlocks/ In Lefty, update dbo.Righty. The update starts running, but is blocked, and sits there waiting for dbo.Righty to commit or roll back.
  • 20. Slides & scripts: BrentOzar.com/sql/deadlocks/ The situation so far: Left window has: • dbo.Lefty exclusive lock • Wants a lock on dbo.Righty, but can’t get it (yet) Right window has: • dbo.Righty exclusive lock
  • 21. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 22. Slides & scripts: BrentOzar.com/sql/deadlocks/ The situation so far: Left window has: • dbo.Lefty exclusive lock • Wants a lock on dbo.Righty, but can’t get it (yet) Right window has: • dbo.Righty exclusive lock
  • 23. Slides & scripts: BrentOzar.com/sql/deadlocks/ But let’s do something terrible. In the right hand window, don’t commit or roll back: instead, try to get a lock on dbo.Lefty.
  • 24. Slides & scripts: BrentOzar.com/sql/deadlocks/ Things are going to happen fast. I’ll describe what’s going to happen before I hit F5: • The right window will want to run, but…
  • 25. Slides & scripts: BrentOzar.com/sql/deadlocks/ The situation will become: Left window has: • dbo.Lefty exclusive lock • Wants a lock on dbo.Righty, but can’t get it (ever) Right window has: • dbo.Righty exclusive lock • Wants a lock on dbo.Lefty, but can’t get it (ever)
  • 26. Slides & scripts: BrentOzar.com/sql/deadlocks/ Things are going to happen fast. I’ll describe what’s going to happen before I hit F5: • The right window will want to run, but… • Neither side will be able to make progress • SQL Server’s deadlock monitor wakes up every 5 seconds, and when he does, he’ll see the problem • He’ll pick the query that’s the easiest to roll back, and kill it
  • 27. Slides & scripts: BrentOzar.com/sql/deadlocks/ I hit F5 in the right window, and… Within 5 seconds, SQL Server kills one.
  • 28. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 29. Slides & scripts: BrentOzar.com/sql/deadlocks/ The root cause: bad ordering Left window has: • dbo.Lefty exclusive lock • Wants a lock on dbo.Righty, but can’t get it (ever) Right window has: • dbo.Righty exclusive lock • Wants a lock on dbo.Lefty, but can’t get it (ever)
  • 30. Slides & scripts: BrentOzar.com/sql/deadlocks/ The fix: better ordering If we work on tables in a consistent order: • Always update dbo.Lefty first, then update dbo.Righty Or: • Always update dbo.Righty first, then update dbo.Lefty We’ll be fine either way, as long as we’re consistent.
  • 31. Slides & scripts: BrentOzar.com/sql/deadlocks/ Trying it: I set up both windows to work on dbo.Lefty first. I hit execute in the left window first, then the right:
  • 32. Slides & scripts: BrentOzar.com/sql/deadlocks/ This sounds bad at first. We have a new problem: blocking. The right window can’t make progress. But that’s actually good: he can’t grab a lock that would block others. The left side is able to keep right on going.
  • 33. Slides & scripts: BrentOzar.com/sql/deadlocks/ Continuing in the left window…
  • 34. Slides & scripts: BrentOzar.com/sql/deadlocks/ Continuing in the left window… When the left finally commits, the right is free to start making progress, and can’t be blocked by the left.
  • 35. Slides & scripts: BrentOzar.com/sql/deadlocks/ The moral of the story Work in tables in a consistent order, like: • Always parents, then children • Or always children, then parents Which one you choose is less important than being ruthlessly consistent. If even one query works out of order, there will be deadlocks.
  • 36. Slides & scripts: BrentOzar.com/sql/deadlocks/ Session agenda Basics: • 3 concurrency issues • 3 ways to fix ‘em all • 1 “fix” that makes things worse: NOLOCK One real fix: work on tables in a consistent order • Demo: unrealistic query • Demo: realistic query Using sp_BlitzLock to find the queries you need to fix We are here.
  • 37. Slides & scripts: BrentOzar.com/sql/deadlocks/ Real-world scenario At Stack Overflow, you can up/downvote questions. Voting
  • 38. Slides & scripts: BrentOzar.com/sql/deadlocks/ What happens when you vote Update your Users.LastAccessDate column to show that you’ve been accessing the site Insert a row in the Votes table Add one point to the question’s score (by updating its row in Posts (Q&A)) Add one point to the question-asker’s reputation (by updating their row in Users, set Reputation + 1)
  • 39. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 40. Slides & scripts: BrentOzar.com/sql/deadlocks/ How it goes wrong What if these two happen at the exact same time: User A upvotes a question owned by UserB UserB upvotes a question owned by UserA
  • 41. Slides & scripts: BrentOzar.com/sql/deadlocks/ Just for this demo
  • 42. Slides & scripts: BrentOzar.com/sql/deadlocks/ Start these two at the same time And one will always lose. (Which one? Tough to tell.)
  • 43. Slides & scripts: BrentOzar.com/sql/deadlocks/ First, we lock our own row Last, we try to lock someone else’s
  • 44. Slides & scripts: BrentOzar.com/sql/deadlocks/ Will ordering help? What if we move all the user updates to the top? Just for this demo
  • 45. Slides & scripts: BrentOzar.com/sql/deadlocks/ Still screwed. It’s not enough to lock tables in the same order: we also need to touch them as few times as practical.
  • 46. Slides & scripts: BrentOzar.com/sql/deadlocks/ Could we update both users at once? How might we solve this problem?
  • 47. Slides & scripts: BrentOzar.com/sql/deadlocks/ Ways to fix it “Just remove the waitfor” = “make it all faster” • Get faster hardware • Tune indexes on the underlying tables • Don’t hold transactions open on the app side Try merging both Users updates into a single query (where it’s the Voter, OR it’s the question-owner) Do the LastAccessDate update outside of the transaction (does it really matter?)
  • 48. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 49. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 50. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 51. Slides & scripts: BrentOzar.com/sql/deadlocks/ It works though! No deadlocks. Well, kinda: there’s a catch. Notice the runtimes.
  • 52. Slides & scripts: BrentOzar.com/sql/deadlocks/ The longer it takes before others can start work.
  • 53. Slides & scripts: BrentOzar.com/sql/deadlocks/ Another approach Do we really need your Last Access Date to be part of the transaction?
  • 54. Slides & scripts: BrentOzar.com/sql/deadlocks/ Run ‘em both at the same time… No deadlocks, AND they both finish in 10 seconds!
  • 55. Slides & scripts: BrentOzar.com/sql/deadlocks/ The more you fix, the faster it goes “Just remove the waitfor” = “make it all faster” • Get faster hardware • Tune indexes on the underlying tables • Don’t hold transactions open on the app side Try merging both Users updates into a single query (where it’s the Voter, OR it’s the question-owner) Do the LastAccessDate update outside of the transaction (does it really matter?)
  • 56. Slides & scripts: BrentOzar.com/sql/deadlocks/ Session agenda Basics: • 3 concurrency issues • 3 ways to fix ‘em all • 1 “fix” that makes things worse: NOLOCK One real fix: work on tables in a consistent order • Demo: unrealistic query • Demo: realistic query Using sp_BlitzLock to find the queries you need to fix
  • 57. Slides & scripts: BrentOzar.com/sql/deadlocks/ sp_BlitzLock helps you spot ‘em. Thanks to SQL 2012 or newer, the default system health Extended Events session, and Erik Darling:
  • 58. Slides & scripts: BrentOzar.com/sql/deadlocks/ Top result set: list of deadlocks Scroll to the far right, and you also get the deadlock graph. Save it as an XDL file, then re- open it in SSMS or in SentryOne Plan Explorer.
  • 59. Slides & scripts: BrentOzar.com/sql/deadlocks/ Bottom results: analytics This is what really helps me get to the bottom of it:
  • 60. Slides & scripts: BrentOzar.com/sql/deadlocks/ Bottom results: analytics Tables & indexes: use my D.E.A.T.H. Method on ‘em Queries: hit tables in a consistent order, tune txns
  • 61. Slides & scripts: BrentOzar.com/sql/deadlocks/
  • 62. Slides & scripts: BrentOzar.com/sql/deadlocks/ 3 ways to fix concurrency issues 1. Have enough indexes to make your queries fast, but not so many that they slow down DUIs, making them hold more locks for longer times. (I cover this in Mastering Index Tuning.) 2. Tune your transactional code. (This module focuses on this topic.) 3. Use the right isolation level for your app’s needs. (I cover this in Mastering Server Tuning.)