There is a picture in the database called
Harem Table of , Every day, millions of new little sisters plug into the watch , time passes very quickly , Round the clock , Love will come in time , After a long time , There are billions of
Cute girl data , See billions of little sisters , Every night , I'm so worried , So many little sisters , I'll flip a card ?
The way is, of course, to streamline the administration , Delete those
age>18 Of , Leave a place for the young sisters ...
So I added a small program to the database to execute it regularly , Every Sunday , Run the following script automatically
delete from ` Harem ` where age>18
I feel good about myself at first , I found out later that it was wrong , Every Sunday , This script runs all day , Running a little longer is a small thing , The point is this great Sunday , I want to read the data of this table again , I can't read it , How is an empty sentence , I'm so hard !
I can't make it up , The real background is a huge data table in the company , Once the historical data is cleaned up , Our program just can't read the data of this table , Report a mistake crazily , Later I found out , It turns out that the design of timed deletion statements is unreasonable , Causes data in the database to be locked by rows (
Row lock) Upgrade to table lock (
Table lock) 了 .
In the process of solving this problem, I learned about database lock , Here is the learning achievement , Share with you , I hope that's helpful .
I will discuss SQL Server Lock mechanism and how to use SQL Server Standard dynamic management view monitoring SQL Server In the lock , I believe that other data locks are the same , It has certain reference significance .
Lay the groundwork for knowledge
Before I start to explain SQL Server Before locking the architecture , Let's take a moment to describe ACID（ Atomicity , Uniformity , Isolation and persistence ） What is it? .ACID Database management system （DBMS） In the process of writing or updating data , For the sake of security （transaction） Is correct and reliable , Four characteristics required ： Atomicity （atomicity, Or indivisibility ）、 Uniformity （consistency）、 Isolation, （isolation, Also called independence ）、 persistence （durability）.
A business （transaction） All operations in , Or complete it all , Or not at all , It doesn't end in the middle . An error occurred during the execution of the transaction , Will be rolled back （Rollback） Status to the beginning of the transaction , It's like this transaction has never been executed . namely , The business is indivisible 、 Irreducible .
Before and after transaction start , The integrity of the database is not compromised . This means that the data to be written must fully comply with all default constraints 、 trigger 、 Cascade rollback, etc .
The ability of a database to allow multiple concurrent transactions to read, write, and modify its data simultaneously , Isolation can prevent data inconsistency caused by cross execution when multiple transactions are executed concurrently . Transaction isolation is divided into different levels , Include uncommitted reads （Read uncommitted）、 Submit to read （read committed）、 Repeatable （repeatable read） And serialization （Serializable）.
After transaction ends , Changes to data are permanent , Even if the system fails, it will not be lost .
source : Wikipedia https://zh.wikipedia.org/wiki/ACID
A transaction is the smallest stack in a process , Can't be divided into smaller parts . Besides , Some transaction groups can execute in sequence , But as we explained in the principle of atomicity , Even if one of the transactions fails , All transaction blocks will also fail .
Locking is a mechanism to ensure data consistency .SQL Server Lock the object when the transaction starts . After the transaction completes ,SQL Server Will release the locked object . According to SQL Server Process type and isolation level change this locking mode . These lock modes are ：
SQL Server Has lock hierarchy , Used to get locked objects in this hierarchy . The database is at the top of the hierarchy , The line is at the bottom . The following figure illustrates SQL Server The lock hierarchy of .
share （S） lock (Shared (S) Locks)
When you need to read objects , This lock type will occur . This type of lock does not cause too much problems .
Monopoly （X） lock (Exclusive (X) Locks)
When this lock type occurs , Occurs to prevent other transactions from modifying or accessing the locked object .
to update （U） lock (Update (U) Locks)
This lock type is similar to exclusive lock , But it has some differences . We can divide the update operation into different stages ： Read phase and write phase . In the read phase ,SQL Server You do not want other transactions to have access to this object for changes , therefore ,SQL Server Use update lock .
Intent to lock in (Intent Locks)
When SQL Server Want to get a share on some of the lower resources in the lock hierarchy （S） Lock or exclusive （X） When locked , Intention lock will occur . actually , When SQL Server When getting a lock on a page or line , The intention lock needs to be set in the table .
SQL Server locking
After learning these background knowledge , Let's try again SQL Server Find these locks .SQL Server Provides many dynamic management views to access metrics . To identify SQL Server lock , We can use sys.dm_tran_locks View . In this view , We can find a lot of information about the current active lock management .
In the first example , We'll create a demo table that doesn't contain any indexes , And try to update this presentation .
CREATE TABLE TestBlock (Id INT , Nm VARCHAR(100)) INSERT INTO TestBlock values(1,'CodingSight') In this step, we will create an open transaction and analyze the locked resources. BEGIN TRAN UPDATE TestBlock SET Nm='NewValue_CodingSight' where Id=1 select @@SPID
And then we get SPID after , Let's see
sys.dm_tran_lock What's in the view .
select * from sys.dm_tran_locks WHERE request_session_id=74
This view returns a lot of information about the active lock resource , But it's some data that we can't understand . therefore , We must put
sys.dm_tran_locks join Some other watches .
SELECT dm_tran_locks.request_session_id, dm_tran_locks.resource_database_id, DB_NAME(dm_tran_locks.resource_database_id) AS dbname, CASE WHEN resource_type = 'OBJECT' THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id) ELSE OBJECT_NAME(partitions.OBJECT_ID) END AS ObjectName, partitions.index_id, indexes.name AS index_name, dm_tran_locks.resource_type, dm_tran_locks.resource_description, dm_tran_locks.resource_associated_entity_id, dm_tran_locks.request_mode, dm_tran_locks.request_status FROM sys.dm_tran_locks LEFT JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id WHERE resource_associated_entity_id > 0 AND resource_database_id = DB_ID() and request_session_id=74 ORDER BY request_session_id, resource_associated_entity_id
In the diagram above , You can see the locked resources .SQL Server Get the exclusive lock in the row .（RID： Row identifier used to lock a single row in the heap ） meanwhile ,SQL Server Get exclusive locks and TestBlock Signify to lock . This means that SQL Server Before releasing the lock , No other process can read this resource , This is a SQL Server The basic locking mechanism in .
Now? , We'll fill in the test table with some composite data .
TRUNCATE TABLE TestBlock DECLARE @K AS INT=0 WHILE @K <8000 BEGIN INSERT TestBlock VALUES(@K, CAST(@K AS varchar(10)) + ' Value' ) SET @K=@K+1 END --After completing this step, we will run two queries and check the sys.dm_tran_locks view. BEGIN TRAN UPDATE TestBlock set Nm ='New_Value' where Id<5000
In the query above ,SQL Server Get the exclusive lock for each line . Now? , We will run another query .
BEGIN TRAN UPDATE TestBlock set Nm ='New_Value' where Id<7000
In the query above ,SQL Server An exclusive lock was created on the table , because SQL Server Try to get a lot of... For these lines that will be updated RID lock , This situation will lead to a large amount of resource consumption in the database engine , therefore ,SQL Server This exclusive lock is automatically moved to the parent object in the lock hierarchy (Table). We define this mechanism as Lock Escalation, This is what I said at the beginning of the article, lock upgrade , It is upgraded from row lock to table lock .
According to the description of the official documents, there are any of the following conditions , Will trigger lock escalation ：
Single Transact-SQL Statement gets at least... On a single non partitioned table or index 5,000 A lock .
Single Transact-SQL Statement gets at least... On a single partition of the partitioned table 5,000 A lock , also ALTER TABLE SET LOCK_ESCALATION Option set to AUTO.
The number of locks in the database engine instance exceeds the memory or configuration threshold .
How to avoid lock upgrade
The easiest way to prevent lock escalation , The safest way is to keep the transaction short , And reduce the lock space of expensive query , So that the lock escalation threshold is not exceeded , There are several ways to achieve this .
Break down a large number of operations into a few smaller operations
for example , At the beginning of my article, I said to delete the data of my little sister among billions of data ：
delete from ` Harem ` where age>18
We can not be so anxious , Delete only... At a time 500 individual , You can significantly reduce the cumulative number of locks per transaction and prevent lock escalation . for example ：
SET ROWCOUNT 500 delete_more: delete from ` Harem ` where age>18 IF @@ROWCOUNT > 0 GOTO delete_more SET ROWCOUNT 0
Create an index to make the query as efficient as possible to reduce the lock space of the query
If there is no index, table scanning may increase the possibility of lock upgrade , It's even scarier , It increases the possibility of deadlock , And it usually has a negative impact on concurrency and performance .
Create an appropriate index based on the query criteria , Maximize the efficiency of index lookup , One goal of this optimization is to make index lookups return as few rows as possible , To minimize the cost of the query .
If other SPID Currently holds incompatible table locks , Lock upgrade will not occur
Lock upgrade is always upgraded to table lock , Instead of upgrading to page lock . If the other SPID Holding conflicts with upgraded table locks IX（intent exclusive） lock , Then it gets a finer level （ That's ok ,key Or page ） lock , Regular additional upgrade attempts . Table level IX（intent exclusive） Locking does not lock any rows or pages , But it's still with upgraded S（ share ） or X（ Monopoly ）TAB Locking is not compatible .
As shown below , If an operation is always completed in less than an hour , You can create... With the following code sql, And arrange to execute before the operation
BEGIN TRAN SELECT * FROM mytable (UPDLOCK, HOLDLOCK) WHERE 1=0 WAITFOR DELAY '1:00:00' COMMIT TRAN
This query is in mytable Get on and keep IX Lock for an hour , This prevents lock escalation of the table during this period .
Okay , Don't say the , Young ladies are fighting again because they don't want to leave me ( Deadlock ).
SQL Server Transaction Locking and Row Versioning Guide https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-guides/jj856598(v=sql.110)
SQL Server, Locks Object https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-2017
How to resolve blocking problems that are caused by lock escalation in SQL Server https://support.microsoft.com/es-ve/help/323630/how-to-resolve-blocking-problems-that-are-caused-by-lock-escalation-in
Main concept of SQL Server locking https://codingsight.com/main-concept-of-sql-server-locking/