এখনও কীভাবে তালাবদ্ধ থাকা ক্যোয়ারীটি কীভাবে সন্ধান করবেন?


15

অনুসন্ধান sys.dm_tran_locksনা DMV শো আমাদের যা সেশন (SPIDs) টেবিল পাতা এবং সারি মত সম্পদের উপর কেশ ধারণ করা হয়।

অধিগ্রহণ করা প্রতিটি লকের জন্য, কোন এসকিউএল বিবৃতি (মুছুন, সন্নিবেশ করান, আপডেট করুন বা নির্বাচন করুন) সেই লকটি তৈরি করেছে তা নির্ধারণ করার কোনও উপায় আছে কি?

আমি জানি যে ডিএমভি- এর most_recent_query_handleকলামটি sys.dm_exec_connectionsআমাদের সম্পাদিত শেষ ক্যোয়ারীর পাঠ্য দেয়, তবে একই সেশনের (এসপিআইডি) অধীনে অন্যান্য কোয়েরিগুলি কয়েকবার দৌড়েছিল এবং এখনও তালাবন্ধ রয়েছে।

আমি ইতিমধ্যে sp_whoisactiveপ্রক্রিয়াটি ব্যবহার করেছি (অ্যাডাম মাচানিক থেকে) এবং এটি কেবলমাত্র এই মুহূর্তে ইনপুট বাফারে থাকা কোয়েরিটি দেখায় (মনে করুন DBCC INPUTBUFFER @spid), যা সর্বদা নয় (এবং আমার ক্ষেত্রে সাধারণত কখনও হয় না) সেই প্রশ্নটি যা লকটি অর্জন করেছিল।

উদাহরণ স্বরূপ:

  1. ওপেন লেনদেন / সেশন
  2. একটি বিবৃতি কার্যকর করুন (যা কোনও সংস্থার উপর একটি লক ধারণ করে)
  3. একই অধিবেশনটিতে অন্য বিবৃতি কার্যকর করুন
  4. অন্য একটি লেনদেন / সেশন খুলুন এবং ধাপ 2 এ লক হওয়া সংস্থানটি সংশোধন করার চেষ্টা করুন।

sp_whoisactiveকার্যপ্রণালী পদক্ষেপ 3, যা লক জন্য দায়ী, এবং এইভাবে না দরকারী নয় এ বিবৃতি বাতলান হবে।

এই প্রশ্নটি উত্পাদনের অবরুদ্ধ পরিস্থিতিগুলির মূল কারণ অনুসন্ধান করতে, ব্লকড প্রসেস রিপোর্টগুলি বৈশিষ্ট্যটি ব্যবহার করে একটি বিশ্লেষণ করে এসেছিল । প্রতিটি লেনদেন বেশ কয়েকটি অনুসন্ধান চালায় এবং বেশিরভাগ সময় শেষটি (যা বিপিআরে ইনপুট বাফারে প্রদর্শিত হয়) খুব কমই লকটি ধারণ করে।

আমার একটি ফলো-আপ প্রশ্ন রয়েছে: ব্লকিং কোয়েরিগুলি কার্যকরভাবে চিহ্নিত করার ফ্রেমওয়ার্ক

উত্তর:


15

এসকিউএল সার্ভার যে আদেশগুলি 1,2 কার্যকর করা হয়েছে তার ইতিহাস রাখে না । আপনি কী কী বস্তুতে লক রয়েছে তা নির্ধারণ করতে পারেন, তবে আপনি প্রয়োজনীয়ভাবে দেখতে পারবেন না যে কী বিবৃতিতে এই লকগুলি তৈরি হয়েছিল।

উদাহরণস্বরূপ, যদি আপনি এই বিবৃতিটি কার্যকর করেন:

BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES

এবং সর্বাধিক সাম্প্রতিক এসকিএল হ্যান্ডেলের মাধ্যমে এসকিউএল পাঠ্যটি দেখুন, আপনি দেখতে পাবেন যে বিবৃতিটি প্রদর্শিত হবে। তবে, সেশনটি যদি এটি করে:

BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
GO
SELECT *
FROM dbo.TestLock;
GO

SELECT * FROM dbo.TestLock;লেনদেনটি প্রতিশ্রুতিবদ্ধ না হওয়া সত্ত্বেও আপনি কেবল বিবৃতি দেখতে পাবেন এবং বিবৃতিটি INSERTপাঠকদের dbo.TestLockটেবিলের বিরুদ্ধে আটকাচ্ছে ।

আমি অনির্বাচিত লেনদেনগুলির সন্ধানের জন্য এটি ব্যবহার করি যা অন্যান্য সেশনগুলিকে অবরুদ্ধ করে:

/*
    This query shows sessions that are blocking other sessions, including sessions that are 
    not currently processing requests (for instance, they have an open, uncommitted transaction).

    By:  Max Vernon, 2017-03-20
*/
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; --reduce possible blocking by this query.

USE tempdb;

IF OBJECT_ID('tempdb..#dm_tran_session_transactions') IS NOT NULL
DROP TABLE #dm_tran_session_transactions;
SELECT *
INTO #dm_tran_session_transactions
FROM sys.dm_tran_session_transactions;

IF OBJECT_ID('tempdb..#dm_exec_connections') IS NOT NULL
DROP TABLE #dm_exec_connections;
SELECT *
INTO #dm_exec_connections
FROM sys.dm_exec_connections;

IF OBJECT_ID('tempdb..#dm_os_waiting_tasks') IS NOT NULL
DROP TABLE #dm_os_waiting_tasks;
SELECT *
INTO #dm_os_waiting_tasks
FROM sys.dm_os_waiting_tasks;

IF OBJECT_ID('tempdb..#dm_exec_sessions') IS NOT NULL
DROP TABLE #dm_exec_sessions;
SELECT *
INTO #dm_exec_sessions
FROM sys.dm_exec_sessions;

IF OBJECT_ID('tempdb..#dm_exec_requests') IS NOT NULL
DROP TABLE #dm_exec_requests;
SELECT *
INTO #dm_exec_requests
FROM sys.dm_exec_requests;

;WITH IsolationLevels AS 
(
    SELECT v.*
    FROM (VALUES 
              (0, 'Unspecified')
            , (1, 'Read Uncomitted')
            , (2, 'Read Committed')
            , (3, 'Repeatable')
            , (4, 'Serializable')
            , (5, 'Snapshot')
        ) v(Level, Description)
)
, trans AS 
(
    SELECT dtst.session_id
        , blocking_sesion_id = 0
        , Type = 'Transaction'
        , QueryText = dest.text
    FROM #dm_tran_session_transactions dtst 
        LEFT JOIN #dm_exec_connections dec ON dtst.session_id = dec.session_id
    OUTER APPLY sys.dm_exec_sql_text(dec.most_recent_sql_handle) dest
)
, tasks AS 
(
    SELECT dowt.session_id
        , dowt.blocking_session_id
        , Type = 'Waiting Task'
        , QueryText = dest.text
    FROM #dm_os_waiting_tasks dowt
        LEFT JOIN #dm_exec_connections dec ON dowt.session_id = dec.session_id
    OUTER APPLY sys.dm_exec_sql_text(dec.most_recent_sql_handle) dest
    WHERE dowt.blocking_session_id IS NOT NULL
)
, requests AS 
(
SELECT des.session_id
    , der.blocking_session_id
    , Type = 'Session Request'
    , QueryText = dest.text
FROM #dm_exec_sessions des
    INNER JOIN #dm_exec_requests der ON des.session_id = der.session_id
OUTER APPLY sys.dm_exec_sql_text(der.sql_handle) dest
WHERE der.blocking_session_id IS NOT NULL
    AND der.blocking_session_id > 0 
)
, Agg AS (
    SELECT SessionID = tr.session_id
        , ItemType = tr.Type
        , CountOfBlockedSessions = (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = tr.session_id)
        , BlockedBySessionID = tr.blocking_sesion_id
        , QueryText = tr.QueryText
    FROM trans tr
    WHERE EXISTS (
        SELECT 1
        FROM requests r
        WHERE r.blocking_session_id = tr.session_id
        )
    UNION ALL
    SELECT ta.session_id
        , ta.Type
        , CountOfBlockedSessions = (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = ta.session_id)
        , BlockedBySessionID = ta.blocking_session_id
        , ta.QueryText
    FROM tasks ta
    UNION ALL
    SELECT rq.session_id
        , rq.Type
        , CountOfBlockedSessions =  (SELECT COUNT(*) FROM requests r WHERE r.blocking_session_id = rq.session_id)
        , BlockedBySessionID = rq.blocking_session_id
        , rq.QueryText
    FROM requests rq
)
SELECT agg.SessionID
    , ItemType = STUFF((SELECT ', ' + COALESCE(a.ItemType, '') FROM agg a WHERE a.SessionID = agg.SessionID ORDER BY a.ItemType FOR XML PATH ('')), 1, 2, '')
    , agg.BlockedBySessionID
    , agg.QueryText
    , agg.CountOfBlockedSessions
    , des.host_name
    , des.login_name
    , des.is_user_process
    , des.program_name
    , des.status
    , TransactionIsolationLevel = il.Description
FROM agg 
    LEFT JOIN #dm_exec_sessions des ON agg.SessionID = des.session_id
    LEFT JOIN IsolationLevels il ON des.transaction_isolation_level = il.Level
GROUP BY agg.SessionID
    , agg.BlockedBySessionID
    , agg.CountOfBlockedSessions
    , agg.QueryText
    , des.host_name
    , des.login_name
    , des.is_user_process
    , des.program_name
    , des.status
    , il.Description
ORDER BY 
    agg.BlockedBySessionID
    , agg.CountOfBlockedSessions
    , agg.SessionID;

যদি আমরা বেশ কয়েকটি ক্যোয়ারী উইন্ডো সহ এসএসএমএসে একটি সাধারণ টেস্ট-বিছানা সেটআপ করি তবে আমরা দেখতে পাচ্ছি যে আমরা কেবলমাত্র সক্রিয় বিবৃতিটি দেখতে পাচ্ছি।

প্রথম ক্যোয়ারী উইন্ডোতে এটি চালান:

CREATE TABLE dbo.TestLock
(
    id int NOT NULL IDENTITY(1,1)
);
BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES

দ্বিতীয় উইন্ডোতে, এটি চালান:

SELECT *
FROM  dbo.TestLock

এখন, যদি আমরা উপরে থেকে নিরীক্ষণ করা অবরুদ্ধ লেনদেন কোয়েরিটি চালাই, আমরা নীচের আউটপুটটি দেখতে পাচ্ছি:

╔═══════════╦═══════════════════════════════╦═════ ═══════════════╦══════════════════════════════════ ═══════╗
Ession সেশনআইডি tem আইটেম টাইপ ║ ব্লকডবাইসেশন আইডি ║ ক্যোরি টেক্সট ║
╠═══════════╬═══════════════════════════════╬═════ ═══════════════╬══════════════════════════════════ ═══════╣
║ 67 ║ লেনদেন ║ 0 ║ শুরু লেনদেন ║
Bo ║ ║ d dbo.TestLock মধ্যে মূল্য অন্তর্ভুক্ত করুন ║
║ 68 ║ সেশন অনুরোধ, অপেক্ষার কার্য ║ 67 ║ নির্বাচন করুন * ║
D ║ ║ d Dbo.TestLock RO থেকে ║
╚═══════════╩═══════════════════════════════╩═════ ═══════════════╩══════════════════════════════════ ═══════╝

(আমি ফলাফলের শেষে থেকে কিছু অপ্রাসঙ্গিক কলামগুলি সরিয়ে ফেলেছি)।

এখন, যদি আমরা এখানে প্রথম ক্যোয়ারী উইন্ডোটি পরিবর্তন করি:

BEGIN TRANSACTION
INSERT INTO dbo.TestLock DEFAULT VALUES
GO
SELECT *
FROM dbo.TestLock;
GO

এবং ২ য় ক্যোয়ারী উইন্ডোটি পুনরায় রান করুন:

SELECT *
FROM  dbo.TestLock

আমরা এই আউটপুটটি অবরুদ্ধ লেনদেনের ক্যোয়ারী থেকে দেখতে পাব:

╔═══════════╦═══════════════════════════════╦═════ ═══════════════╦════════════════════╗
Ession সেশনআইডি tem আইটেম টাইপ ║ ব্লকডবাইসেশন আইডি ║ ক্যোরি টেক্সট ║
╠═══════════╬═══════════════════════════════╬═════ ═══════════════╬════════════════════╣
║ 67 ║ লেনদেন ║ 0 ║ নির্বাচন করুন * ║
D ║ ║ ║ Dbo.TestLock থেকে; ║
║ 68 ║ সেশন অনুরোধ, অপেক্ষার কার্য ║ 67 ║ নির্বাচন করুন * ║
D ║ ║ d Dbo.TestLock RO থেকে ║
╚═══════════╩═══════════════════════════════╩═════ ═══════════════╩════════════════════╝

1 - সম্পূর্ণ সত্য নয়। সেখানে কার্যপ্রণালী ক্যাশে, যা হতে পারে বিবৃতি লক জন্য দায়ী থাকে। তবে, বিবৃতিটি লকের প্রকৃত কারণ তা নির্ধারণ করা সহজ নয় কারণ ক্যাশে অনেকগুলি প্রশ্ন থাকতে পারে যা প্রশ্নে উত্সটিকে স্পর্শ করে।

আমার পদ্ধতির ক্যাশে খুব ব্যস্ত না হওয়ায় নীচের পরীক্ষার উপরের পরীক্ষার প্রশ্নের জন্য ক্যোয়ারী প্ল্যান দেখায়।

SELECT TOP(30) t.text
    , p.query_plan
    , deqs.execution_count
    , deqs.total_elapsed_time
    , deqs.total_logical_reads
    , deqs.total_logical_writes
    , deqs.total_logical_writes
    , deqs.total_rows
    , deqs.total_worker_time
    , deqs.*
FROM sys.dm_exec_query_stats deqs
OUTER APPLY sys.dm_exec_sql_text(deqs.sql_handle) t 
OUTER APPLY sys.dm_exec_query_plan(deqs.plan_handle) p
WHERE t.text LIKE '%dbo.TestLock%'  --change this to suit your needs
    AND t.text NOT LIKE '/\/\/\/\/EXCLUDE ME/\/\/\/\/\'
ORDER BY 
    deqs.total_worker_time DESC;

এই প্রশ্নের সাথে ফলাফল হতে পারে আপনি অভিযুক্ত ব্যক্তি খুঁজে পেতে দিই, কিন্তু সচেতন হতে হবে, পরিদর্শন ভালো পদ্ধতি ক্যাশে বেশ একটি ব্যস্ত সিস্টেমে দাবিতে হতে পারে।

2 SQL সার্ভার 2016 এবং উপরোক্ত প্রস্তাব ক্যোয়ারী স্টোর , যা করে মৃত্যুদন্ড কার্যকর প্রশ্নের সম্পূর্ণ ইতিহাস ধরে রাখা।


ধন্যবাদ @ ম্যাক্স, খুব ভালভাবে ব্যাখ্যা করা হয়েছে। Blocked Process Reportsউত্পাদনের অবরুদ্ধ পরিস্থিতিগুলির মূল কারণ অনুসন্ধান করার জন্য বৈশিষ্ট্য বিশ্লেষণ করার সময় এই সন্দেহের জন্ম হয়েছিল । প্রতিটি লেনদেন বেশ কয়েকটি অনুসন্ধান চালায় এবং বেশিরভাগ সময় শেষটি (যা বিপিআরে ইনপুট বাফারে প্রদর্শিত হয়) খুব কমই লকটি ধারণ করে। দেখে মনে হচ্ছে এটি সমাধানের জন্য আমার শেষ উত্স হ'ল প্রতিটি সেশনের অধীনে কি কি প্রশ্নগুলি চলেছিল তা আমাকে জানানোর জন্য একটি হালকা এক্সএভেন্টস সেশন সেট করা। আপনি যদি এর একটি উদাহরণ দেখাচ্ছে এমন একটি নিবন্ধ জানেন তবে আমি কৃতজ্ঞ হব।
ট্যানিটেল

এছাড়াও ক্যোয়ারী স্টোর সম্পর্কিত, এটি খুব দরকারী, তবে এসপিআইডি তথ্যের অভাব রয়েছে। যাই হোক ধন্যবাদ.
ট্যানিটেল


6

ম্যাক্সের উত্তরের পরিপূরক করতে আমি নীচের ইউটিলিটিগুলি অত্যন্ত দরকারী:

আমি যখন Beta- এ গভীর ডুব দিতে চাই এবং কী এবং কীভাবে কীভাবে ব্লকিংয়ের উদ্ভব হয়েছিল তা বিশ্লেষণ করতে চাই - যা অত্যন্ত কার্যকর in

বিটা_লকিনফো হ'ল একটি সঞ্চিত প্রক্রিয়া যা প্রক্রিয়াগুলি এবং তারা যে লকগুলি ধারণ করে সেগুলি এবং তাদের সক্রিয় লেনদেন সম্পর্কে তথ্য সরবরাহ করে। বিটা_লকিনফোকে একটি ব্লকিং পরিস্থিতি সম্পর্কে যতটা সম্ভব তথ্য সংগ্রহ করার জন্য ডিজাইন করা হয়েছে, যাতে আপনি পরিস্থিতিটি তাত্ক্ষণিকভাবে সন্ধান করতে পারেন এবং পরিস্থিতি বেপরোয়া থাকলে অবরুদ্ধকরণ প্রক্রিয়াটি মেরে ফেলতে পারেন। তারপরে আপনি কীভাবে অবরুদ্ধ পরিস্থিতি তৈরি হয়েছিল তা বুঝতে এবং Beta_lockinfo থেকে আউটপুট বিশ্লেষণ করতে পারেন এবং পরিস্থিতি পুনরায় সংঘটিত হতে রোধ করতে কী পদক্ষেপ গ্রহণ করবে তা বুঝতে পারেন। বিটা_লকইনফো থেকে আউটপুট সমস্ত সক্রিয় প্রক্রিয়া পাশাপাশি লকগুলি সহ প্যাসিভ প্রক্রিয়াগুলি দেখায়, কোন বস্তু তারা লক করে, কোন আদেশটি তারা সর্বশেষ জমা দিয়েছে এবং কোন বিবৃতিটি তারা কার্যকর করছে। আপনি বর্তমান বিবৃতিগুলির জন্য ক্যোয়ারী পরিকল্পনাগুলিও পান।


1
বাহ, যে এরল্যান্ড সোমমারস্কোগ প্রোক আশ্চর্যজনক।
ম্যাক্স ভার্নন

1
হ্যাঁ .. যখন আমাকে অবরুদ্ধকরণের বিশদে গভীর ডুব দিতে হয় তখন আমি এটি ব্যবহার করি।
কিন শাহ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.