রাষ্ট্র পরিবর্তনগুলি মিরর করার সময় কীভাবে একটি ইভেন্ট নোটিফিকেশন তৈরি করা যায় যা একটি কাজ / প্রক্রিয়া চালায়


11

আমি এই প্রশ্নের ক্রমটিতে এই প্রশ্নটি জিজ্ঞাসা করছি কি আমি টিসিপি-এসকিউএল ব্যবহার করে টিসিপি-র মাধ্যমে একটি স্ট্রিং প্রেরণ করতে পারি?

আমার সমস্যাটির এটি সর্বোত্তম সমাধান বলে মনে হচ্ছে যা রিমাস রুসানু প্রকাশ করেছেন তবে ... তিনি যা বলেছেন তা বোঝার এবং তৈরি করার জন্য আমি খুব অপরিণত।

আমি এখনও অবধি মনে করি DATABASE_MIRRORING_STATE_CHANGE এর জন্য একটি বিজ্ঞপ্তি ইভেন্ট তৈরি করার জন্য আমার কী দরকার, আমি কি সঠিক?

আমি যখন এই ইভেন্টের বিজ্ঞপ্তিটি তৈরি করতে পারি তখন এটির ট্রিগারযুক্ত কোনও টেবিলের মধ্যে একটি লাইন প্রবেশ করায়, বিজ্ঞপ্তি থেকে আসা একটি টাইমস্ট্যাম্প এবং একটি আইডি সঞ্চয় করে।

এখন পর্যন্ত আমি প্রতি আইডি প্রতি একটি সতর্কতা স্থাপন করছি, প্রত্যেকে এইরকম একটি কাজ চালাচ্ছে (উদাহরণটি আইডি = 1 এর জন্য):

    DECLARE @state AS varchar(50);
    SELECT @state = mirroring_state_desc FROM SYS.database_mirroring WHERE mirroring_guid IS NOT NULL;
    IF (@state IS null) SET @state = ' ';
    INSERT INTO MirroringAlerts (DateTime, alertID, alertDesc, Sync, alertCreator) values (SYSDATETIME(), 1, 'Principal synchronized with W ', @state, @@SERVERNAME)

মূলত আমি এই ডাটাবেসে একটি অভ্যন্তরীণ লগ তৈরি করছি:

CREATE TABLE [dbo].[MirroringAlerts](
    [DateTime] [datetime] NOT NULL,
    [alertID] [smallint] NOT NULL,
    [alertDesc] [nchar](50) NOT NULL,
    [Sync] [nchar](12) NOT NULL,
    [alertCreator] [nchar](128) NULL
) ON [PRIMARY]

তবে এইভাবে ... সতর্কতাগুলি যথেষ্ট দ্রুত ট্রিগার করা হচ্ছে না ... তাই আমি তথ্য হারাচ্ছি ...

ডেটাবেস মিররিং স্টেট পরিবর্তিত ইভেন্টের জন্য ইভেন্ট নোটিফিকেশন তৈরি করে এই আচরণটি কীভাবে প্রোগ্রাম করবেন তা আপনি আমাকে বলতে পারেন ?

শুভেচ্ছান্তে

উত্তর:


13

পদক্ষেপ 1: বিজ্ঞপ্তিগুলি পাওয়ার জন্য একটি পরিষেবা তৈরি করুন এবং এর জন্য একটি সারি তৈরি করুন:

use msdb;
go

create queue dbm_notifications_queue;
create service dbm_notification_service
    on queue dbm_notifications_queue
    ([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
go

create event notification dbm_notifications
    on server   
    for database_mirroring_state_change
    to service N'dbm_notification_service', N'current database';
go

নোট করুন যে আমি ব্যবহার করছি msdb, এটি কোনও দুর্ঘটনা নয়। সার্ভার স্তর ঘটনা বিজ্ঞপ্তি থেকে পাঠানো হয় কারণ msdbএটা অনেক ভালো করেন তাহলে আপনি পুরো উল্টো কথোপকথন শেষবিন্দু (লক্ষ্য) তৈরি হয় msdbযা যে বোঝা গন্তব্য পরিষেবা এবং কিউ এছাড়া মোতায়েন করা আবশ্যক, msdb

পদক্ষেপ 2: ইভেন্ট বিজ্ঞপ্তি প্রক্রিয়াকরণ পদ্ধতি তৈরি করুন:

use msdb;
go

create table dbm_notifications_errors (
    incident_time datetime not null,
    session_id int not null,
    has_rolled_back bit not null,
    [error_number] int not null,
    [error_message] nvarchar(4000) not null,
    [message_body] varbinary(max));
create clustered index cdx_dbm_notifications_errors 
    on dbm_notifications_errors  (incident_time);
go

create table mirroring_alerts (
    alert_time datetime not null,
    start_time datetime not null,
    processing_time datetime not null,
    database_id smallint not null,
    database_name sysname not null,
    [state] tinyint not null,
    [text_data] nvarchar(max),
    event_data xml not null);
create clustered index cdx_mirroring_alerts
    on mirroring_alerts (alert_time);   
go      

create procedure dbm_notifications_procedure
as
begin
    declare @dh uniqueidentifier, @mt sysname, @raw_body varbinary(max), @xml_body xml; 

    begin transaction;
    begin try;
        receive top(1)
            @dh = conversation_handle,
            @mt = message_type_name,
            @raw_body = message_body
        from dbm_notifications_queue;
        if N'http://schemas.microsoft.com/SQL/Notifications/EventNotification' = @mt
        begin
            set @xml_body = cast(@raw_body as xml);
             -- shred the XML and process it accordingly
             -- IMPORTANT! IMPORTANT!
             -- DO NOT LOOK AT sys.database_mirroring
             -- The view represents the **CURRENT** state
             -- This message reffers to an **EVENT** that had occured
             -- the current state may or may no be relevant for this **PAST** event
            declare @alert_time datetime
                , @start_time datetime
                , @processing_time datetime = getutcdate()
                , @database_id smallint 
                , @database_name sysname
                , @state tinyint
                , @text_data nvarchar(max);

            set @alert_time = @xml_body.value (N'(//EVENT_INSTANCE/PostTime)[1]', 'DATETIME');
            set @start_time = @xml_body.value (N'(//EVENT_INSTANCE/StartTime)[1]', 'DATETIME');
            set @database_id = @xml_body.value (N'(//EVENT_INSTANCE/DatabaseID)[1]', 'SMALLINT');
            set @database_name = @xml_body.value (N'(//EVENT_INSTANCE/DatabaseName)[1]', 'SYSNAME');
            set @state = @xml_body.value (N'(//EVENT_INSTANCE/State)[1]', 'TINYINT');
            set @text_data = @xml_body.value (N'(//EVENT_INSTANCE/TextData)[1]', 'NVARCHAR(MAX)');

            insert into mirroring_alerts (
                alert_time, 
                start_time,
                processing_time,
                database_id,
                database_name,
                [state],
                text_data,
                event_data)
            values (
                @alert_time, 
                @start_time,
                @processing_time,
                @database_id,
                @database_name,
                @state,
                @text_data,
                @xml_body);
        end
        else if N'http://schemas.microsoft.com/SQL/ServiceBroker/Error' = @mt
        begin
        set @xml_body = cast(@raw_body as xml);
        DECLARE @error INT
                , @description NVARCHAR(4000);
        WITH XMLNAMESPACES ('http://schemas.microsoft.com/SQL/ServiceBroker/Error' AS ssb)
        SELECT @error = CAST(@xml_body AS XML).value('(//ssb:Error/ssb:Code)[1]', 'INT'),
            @description = CAST(@xml_body AS XML).value('(//ssb:Error/ssb:Description)[1]', 'NVARCHAR(4000)');          

        insert into dbm_notifications_errors(
            incident_time,
            session_id, 
            has_rolled_back,
            [error_number],
            [error_message],
            [message_body])
        values (
            getutcdate(),
            @@spid,
            0,
            @error,
            @description,
            @raw_body);
            end conversation @dh;
        end
        else if N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' = @mt
        begin
            end conversation @dh;
        end
        commit;
    end try
    begin catch
        declare @xact_state int = xact_state(), 
            @error_number int = error_number(), 
            @error_message nvarchar(4000) = error_message(),
            @has_rolled_back bit = 0;
        if @xact_state = -1
        begin
            -- Doomed transaction, it must rollback
            rollback;
            set @has_rolled_back = 1;
        end
        else if @xact_state = 0
        begin
            -- transaction was already rolled back (deadlock?)
            set @has_rolled_back = 1;
        end
        insert into dbm_notifications_errors(
            incident_time,
            session_id, 
            has_rolled_back,
            [error_number],
            [error_message],
            [message_body])
        values (
            getutcdate(),
            @@spid,
            @has_rolled_back,
            @error_number,
            @error_message,
            @raw_body);
        if (@has_rolled_back = 0)
        begin
            commit;
        end
    end catch
end
go

রাইটিং সার্ভিস ব্রোকার পদ্ধতিটি আপনার মিল-রান কোড অফ নয়। কাউকে অবশ্যই কিছু মানদণ্ড অনুসরণ করতে হবে এবং চতুর্দিকে ত্রৈমাসিকের অঞ্চলে যেতে খুব সহজ to এই কোডটি কিছু ভাল অভ্যাস দেখায়:

  • কোনও লেনদেনে বার্তা প্রেরণাগুলি এবং প্রক্রিয়াজাতকরণ মোড়ক করুন। কোন বুদ্ধিমান, স্পষ্ট।
  • সর্বদা প্রাপ্ত বার্তার প্রকারটি পরীক্ষা করুন। একটি ভাল পরিষেবা ব্রোকার পদ্ধতিটি অবশ্যই পাশ থেকে ডায়ালগটি শেষ করে হ্যান্ডেল Errorএবং EndDialogবার্তাগুলিকে যথাযথভাবে পরিচালনা করতে হবে। হ্যান্ডেল ফাঁস ( sys.conversation_endpointsবৃদ্ধি) এর ফলে ফলাফল না করার ফলে
  • কোনও বার্তা প্রাপ্তি দ্বারা চিহ্নিত করা হয়েছে কিনা তা সর্বদা পরীক্ষা করে দেখুন। কিছু নমুনা পরে @@ রাউকাউন্ট পরীক্ষা করে RECEIVE, যা পুরোপুরি ঠিক। এই নমুনা কোড বার্তা নাম চেক উপর নির্ভর করে (কোনও বার্তা NULL বার্তা প্রকারের নাম বোঝায়) এবং এই কেসটিকে সুস্পষ্টভাবে পরিচালনা করে।
  • একটি প্রসেসিং ত্রুটি সারণী তৈরি করুন। এসএসবি সক্রিয় প্রক্রিয়াগুলির পটভূমি প্রকৃতি ত্রুটিগুলি নিরসন করা সত্যিই কঠিন করে তোলে যদি বার্তাগুলি কেবল w / oa ট্রেসটি হারিয়ে যায়।

এছাড়াও, এই কোডটি হাতের কার্য (ডিবিএম পর্যবেক্ষণ) সম্পর্কিত কিছু ভাল-অনুশীলন কোডও করে:

  • post_time( বিজ্ঞপ্তিটি কখন প্রেরণ করা হয়েছিল? ), start_time( কবে বিজ্ঞপ্তিটি কার্যকর করেছিল এমন ক্রিয়াটি কখন শুরু হয়েছিল? ) এবং processing_time( বিজ্ঞপ্তিটি কখন প্রক্রিয়াজাত করা হয়েছিল ? ) এর মধ্যে পার্থক্য করুন । post_timeএবং start_timeসম্ভবত অভিন্ন বা খুব কাছাকাছি processing_timeহতে পারে তবে এটি কয়েক সেকেন্ড, ঘন্টা, দিন বাদে হতে পারে post_time। অডিট জন্য আকর্ষণীয় এক সাধারণত হয় post_time
  • যেহেতু post_timeএবং processing_timeভিন্ন, এটি সুস্পষ্ট হওয়া উচিত একটি dBm একটি এমনকি বিজ্ঞপ্তিতে কাজের পর্যবেক্ষণ সক্রিয় যে পদ্ধতি কোন ব্যবসা দিকে তাকিয়ে আছে sys.database_mirroringদৃশ্য । সেই দৃশ্য প্রক্রিয়াজাতকরণের মুহুর্তে বর্তমান অবস্থাটি প্রদর্শন করবে , যা ঘটনার সাথে সম্পর্কিত বা নাও থাকতে পারে। যদি সমস্যাটি প্রকাশিত হওয়ার চেয়ে ইভেন্টটি পোস্ট হওয়ার পরে দীর্ঘকাল ধরে প্রক্রিয়াজাত হয় (মনে রাখবেন রক্ষণাবেক্ষণ ডাউনটাইম) তবে ডিবিএম যদি খুব দ্রুত রাষ্ট্র পরিবর্তন করে এবং দুটি (বা আরও) ইভেন্ট পোস্ট করে তবে এটি 'স্বাস্থ্যকর' প্রক্রিয়াকরণেও পরিচালনা করতে পারে সারি (যা ঘন ঘন ঘটে): এই পরিস্থিতিতে আপনার পোস্ট করা কোডের মতো প্রক্রিয়াজাতকরণ ঘটনার সাথে সাথে ইভেন্টটি অডিট করবেন তবে বর্তমান, চূড়ান্ত , স্থিতি রেকর্ড করবে । এ জাতীয় নিরীক্ষা পড়া পরে খুব বিভ্রান্ত হতে পারে।
  • সর্বদা আসল এক্সএমএল ইভেন্টটি নিরীক্ষণ করুন। এইভাবে আপনি পরে এই এক্সএমএলটি অডিট সারণির কলামগুলিতে 'কাটা' হয়নি এমন কোনও তথ্যের জন্য জিজ্ঞাসা করতে পারেন।

পদক্ষেপ 3: পদ্ধতিটি সারিতে সংযুক্ত করুন:

alter queue dbm_notifications_queue
with activation (
    status=on,
    procedure_name = [dbm_notifications_procedure],
    max_queue_readers = 1,
    execute as  owner);

সুতরাং আমি উভয় অংশীদুর এ ঠিক করা উচিত? অধ্যক্ষের কোনও সাক্ষী না থাকলে ব্যর্থতার ক্ষেত্রে কি কিউ প্রক্রিয়া করার / পরীক্ষা করার কোনও উপায় আছে? রাষ্ট্রের সমস্ত পরিবর্তনের পরিস্থিতিতে আমার অ্যাক্সেস রয়েছে কিনা তা জানার জন্য, বা আমার বিজ্ঞপ্তি টেবিলটিতে লগ করা হয়নি এমন কিছু কিছু আছে কিনা
র্যাগনারক

আপনার উভয় অংশীদারদের উপর এটি করা উচিত, ঠিক আছে। অধ্যক্ষের ব্যর্থতার ক্ষেত্রে যদি msdbএখনও অনলাইনে থাকে (যেমন ব্যর্থতা একটি ডিবি ব্যর্থতা, সার্ভার ব্যর্থতা নয়) তবে সারি প্রক্রিয়াকরণটি ঘটবে।
রিমাস রুসানু

পুরষ্কার জন্য ধন্যবাদ। খুব কমপক্ষে, আপনার কাছে এখন "প্রো এসকিউএল সার্ভার ২০০৮ মিররিং" এর একটি অনুলিপি রয়েছে যা আমি শুনছি বিষয়টির একটি ভাল বই।
রেমাস রুসানু

9

Chapter ষ্ঠ অধ্যায়টি পড়ার পরে আমাকে "প্রো এসকিউএল সার্ভার ২০০৮ মিররিং" কিনতে হয়েছিল, আমি এটি করার পদক্ষেপগুলি খুঁজে পেয়েছি:

পরিষেবা ব্রোকার সক্ষম কিনা তা পরীক্ষা করুন

SELECT CASE is_broker_enabled
WHEN 1 Then 'Enabled'
ELSE 'Disabled'
END
FROM sys.databases
WHERE name = 'DataBaseName'

যদি না হয়, চালান

ALTER DATABASE DataBaseName set ENABLE_BROKER;

নোটিফিকেশন ইভেন্টটি আসার সাথে সাথে আমরা ট্রিগার করতে চাইলে সঞ্চিত প্রক্রিয়াটি তৈরি করুন:

CREATE PROCEDURE dbo.dba_MirroringStateChanged
AS
DECLARE @Message XML,
        @DBName sysname,
        @MirrorStateChange INT,
        @ServerName sysname,
        @PostTime datetime,
        @SPID INT,
        @TextData NVARCHAR(500),
        @DatabaseID INT,
        @TransactionsID INT,
        @StartTime datetime;
SET NOCOUNT ON;
-- Receive first unread message in service broker queue
RECEIVE TOP (1)
@Message = CAST(message_body AS XML)
FROM DBMirrorQueue;

BEGIN TRY
    -- Parse state change and database affected
    -- 7 or 8 = database failing over,
    --11 = synchronizing,
    --1 or 2 = synchronized
    SET @MirrorStateChange =
    @Message.value('(/EVENT_INSTANCE/State)[1]', 'int');
    SET @DBName =
    @Message.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'sysname');
    SET @ServerName =
    @Message.value('(/EVENT_INSTANCE/ServerName)[1]', 'sysname');
    SET @PostTime =
    @Message.value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime');
    SET @SPID = @Message.value('(/EVENT_INSTANCE/SPID)[1]', 'int');
    SET @TextData =
    @Message.value('(/EVENT_INSTANCE/TextData)[1]', 'nvarchar(500)');
    SET @DatabaseID =
    @Message.value('(/EVENT_INSTANCE/DatabaseID)[1]', 'int');
    SET @TransactionsID =
    @Message.value('(/EVENT_INSTANCE/TransactionsID)[1]', 'int');
    SET @StartTime =
    @Message.value('(/EVENT_INSTANCE/StartTime)[1]', 'datetime');
END TRY
    BEGIN CATCH
        PRINT 'Parse of mirroring state change message failed.';
    END CATCH

IF (@MirrorStateChange IN (1,2,3,4,5,6,7,8,9,10,11,12,13))
BEGIN

    DECLARE @state AS varchar(50);
    SELECT @state = mirroring_state_desc FROM SYS.database_mirroring WHERE mirroring_guid IS NOT NULL;
    IF (@state IS null) SET @state = ' ';
    INSERT INTO MirroringAlerts (DateTime, alertID, alertDesc, Sync, alertCreator) values (SYSDATETIME(), @MirrorStateChange , @TextData , @state, @SERVERNAME);

END

পরিষেবা এবং সঞ্চিত পদ্ধতির মধ্যে এক ধরণের মধ্যস্থতাকারী হওয়ার জন্য একটি সারি তৈরি করুন, যা আমরা ট্রিগার করতে চাই

-- Create Queue if not exists
IF NOT EXISTS (SELECT 1
    FROM sys.service_queues
    WHERE name = 'DBMirrorQueue')
BEGIN
    CREATE QUEUE DBMirrorQueue
    WITH ACTIVATION (
    PROCEDURE_NAME = dbo.dba_MirroringStateChanged,
    MAX_QUEUE_READERS = 1,
    EXECUTE AS OWNER);
END

ইভেন্টটি সম্পর্কিত হবে এমন পরিষেবা তৈরি করুন

-- Create Service if not exists
IF NOT EXISTS (SELECT 1
    FROM sys.services
    WHERE name = 'DBMirrorService')
BEGIN
    CREATE SERVICE DBMirrorService
    ON QUEUE DBMirrorQueue ([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
END

একটি রুট তৈরি করুন

-- Create Route if not exists
IF NOT EXISTS (SELECT 1
    FROM sys.routes
    WHERE name = 'DBMirrorRoute')
BEGIN
    CREATE ROUTE DBMirrorRoute
    WITH SERVICE_NAME = 'DBMirrorService',
    ADDRESS = 'Local';
END

এবং তারপরে ইভেন্ট নোটিফিকেশন তৈরি করুন

-- Create Event Notification if not exists
IF NOT EXISTS (SELECT 1
    FROM sys.server_event_notifications
    WHERE name = 'DBMirrorStateChange')
BEGIN
    CREATE EVENT NOTIFICATION DBMirrorStateChange
    ON SERVER
    FOR DATABASE_MIRRORING_STATE_CHANGE
    TO SERVICE 'DBMirrorService', 'current database';
END
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.