الالتزام فقط بالتغييرات المحددة التي تم إجراؤها داخل المعاملة والتي قد تؤدي إلى التراجع

StackOverflow https://stackoverflow.com/questions/618928

سؤال

يعد هذا تعديلًا مهمًا من السؤال الأصلي، مما يجعله أكثر إيجازًا ويغطي النقاط التي أثارتها الإجابات الموجودة...

هل من الممكن إجراء تغييرات متعددة على جداول متعددة، داخل معاملة واحدة، والتراجع عن بعض التغييرات فقط؟

في TSQL أدناه، لا أريد التراجع عن أي من التغييرات التي أجراها "myLogSP".ولكن يجب التراجع عن كافة التغييرات التي أجراها مختلف myBusinessSPs إذا لزم الأمر.

BEGIN TRANSACTION  

    EXEC myLogSP

    EXEC @err = myBusinessSPa
    IF (@err <> 0) BEGIN ROLLBACK TRANSACTION RETURN -1 END

    EXEC myLogSP

    EXEC @err = myBusinessSPb
    IF (@err <> 0) BEGIN ROLLBACK TRANSACTION RETURN -1 END

    EXEC myLogSP

    EXEC @err = myBusinessSPc
    IF (@err <> 0) BEGIN ROLLBACK TRANSACTION RETURN -1 END

    EXEC myLogSP

COMMIT TRANSACTION
RETURN 0

الترتيب مهم، يجب أن يحدث myLogSPs بين وبعد myBusinessSPs (يلتقط myLogSPs التغييرات التي أجراها myBusinessSPs)

من المهم أيضًا أن تتم جميع عمليات myBusinessSPs داخل معاملة واحدة للحفاظ على سلامة قاعدة البيانات، والسماح لجميع التغييرات بالتراجع إذا لزم الأمر.

يبدو الأمر كما لو أنني أريد أن يتصرف myLogSPs كما لو أنهم ليسوا جزءًا من المعاملة.إنها مجرد حقيقة مزعجة أن يصادف وجودهم داخل واحد (بحكم الحاجة إلى الاتصال بهم بين myBusinessSPs.)

يحرر:

الإجابة النهائية هي "لا"، والخيار الوحيد هو إعادة تصميم الكود.إما لاستخدام متغيرات الجدول للتسجيل (حيث لا يتم إرجاع المتغيرات) أو إعادة تصميم منطق العمل بحيث لا يتطلب المعاملات...

هل كانت مفيدة؟

المحلول

يستخدم SAVEPOINTس, ، على سبيل المثال.

BEGIN TRANSACTION  

    EXEC myLogSP

    SAVE TRANSACTION savepointA
    EXEC @err = myBusinessSPa
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointA
        COMMIT
        RETURN -1
    END

    EXEC myLogSP

    SAVE TRANSACTION savepointB
    EXEC @err = myBusinessSPb
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointB
        COMMIT
        RETURN -1
    END

    EXEC myLogSP

    SAVE TRANSACTION savepointC
    EXEC @err = myBusinessSPc
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointC
        COMMIT
        RETURN -1
    END

    EXEC myLogSP

COMMIT TRANSACTION

يحرر

استنادًا إلى المعلومات المقدمة حتى الآن (وفهمي لها) يبدو أنه سيتعين عليك إعادة هندسة مقدمي الخدمة الذين يقومون بتسجيل الدخول، إما لاستخدام المتغيرات، أو لاستخدام الملفات، أو للسماح لهم بالعمل "بعد وقوع الحدث" يتبع:

BEGIN TRANSACTION  

    SAVE TRANSACTION savepointA
    EXEC @err = myBusinessSPa
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointA
        EXEC myLogSPA -- the call to myBusinessSPa was attempted/failed
        COMMIT
        RETURN -1
    END

    SAVE TRANSACTION savepointB
    EXEC @err = myBusinessSPb
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointB
        EXEC myLogSPA -- the call to myBusinessSPa originally succeeded
        EXEC myLogSPB -- the call to myBusinessSPb was attempted/failed
        COMMIT
        RETURN -1
    END

    SAVE TRANSACTION savepointC
    EXEC @err = myBusinessSPc
    IF (@err <> 0) BEGIN
        ROLLBACK TRANSACTION savepointC
        EXEC myLogSPA -- the call to myBusinessSPa originally succeeded
        EXEC myLogSPB -- the call to myBusinessSPb originally succeeded
        EXEC myLogSPC -- the call to myBusinessSPc was attempted/failed
        COMMIT
        RETURN -1
    END

    EXEC myLogSPA -- the call to myBusinessSPa succeeded
    EXEC myLogSPB -- the call to myBusinessSPb succeeded
    EXEC myLogSPC -- the call to myBusinessSPc succeeded

COMMIT TRANSACTION

نصائح أخرى

وتحتاج إلى القفز أساسا خارج السياق الحالي. هناك عدة طرق للقيام بذلك. واحد (والتي لم يسبق لي أن حاولت) لاستدعاء CLR للقيام إدراج.

ولعل أفضل طريقة على الرغم من استخدام حقيقة أن المتغيرات الجدول لا تتأثر المعاملة. على سبيل المثال:

CREATE TABLE dbo.Test_Transactions
(
     my_string VARCHAR(20) NOT NULL
)
GO

DECLARE
     @tbl TABLE (my_string VARCHAR(20) NOT NULL)

BEGIN TRANSACTION

INSERT INTO dbo.Test_Transactions (my_string) VALUES ('test point one')

INSERT INTO @tbl (my_string) VALUES ('test point two')

INSERT INTO dbo.Test_Transactions (my_string) VALUES ('test point three')

ROLLBACK TRANSACTION

INSERT INTO dbo.Test_Transactions (my_string) select my_string from @tbl

SELECT * FROM dbo.Test_Transactions
SELECT * FROM @tbl
GO

ولقد كان لدينا الحظ مع وضع إدخالات السجل إلى متغيرات الجدول ثم إدراج الجداول الحقيقية بعد ارتكاب أو العودة.

وOK إذا لم تكن على SQL Server 2008، ثم حاول هذا الأسلوب. انها الفوضى والحل البديل ولكن ينبغي لها أن تعمل. ان الجدول #temp ومتغير الجدول أن تقام مع هيكل ما يتم إرجاعها من قبل ليرة سورية.

create table #templog (fie1d1 int, field2 varchar(10))

declare @templog table (fie1d1 int, field2 varchar(10))

BEGIN TRANSACTION      
insert into #templog
Exec my_proc

insert into @templog (fie1d1, field2)
select t.* from #templog t 
left join @templog t2 on t.fie1d1 = t2.fie1d1 where t2.fie1d1 is null

insert into templog
values (1, 'test')

rollback tran
select * from #templog
select * from templog
select * from @templog

استخدم SAVEPOINTS و <لأ href = "HTTP: / /msdn.microsoft.com/en-us/library/ms173763.aspx "يختلط =" نوفولو noreferrer "> مستويات صفقة عزل .

ولن الطريق السهل أن تكون لتحريك الإدراج سجل خارج الصفقة؟

وأنا لم يكن لديك حقا إجابة لك لتأمين الجدول، وأعتقد أن لديك بالفعل الجواب، وسيكون هناك على هل لديك ليكون تأمين جدول لأن عمود هوية قد تتراجع.

ونقل BEGIN المعاملة إلى بعد إدراج الأول.

وربما كنت قد وضعت إدراج / التحديثات إلى جداول الأعمال في الخاص T1 معاملة الصغيرة والتفاف كل هذه المعاملات في T2 معاملة أخرى الذي ينفذ تحديث جدول سجل وT1 (التحديثات جدول الأعمال) دون أي مستواها السابق. على سبيل المثال:

BEGIN TRANSACTION t2
     <insert to log>
     <execute stored procedure p1>
END TRANSACTION t2

CREATE PROCEDURE p1
AS
     BEGIN TRANSACTION t1
         <insert to business tables>
         <rollback t1 on error>
     END TRANSACTION t1

وأعتقد أنه عند التراجع T1 في الإجراء المخزن هذا سيترك المعاملة الدعوة T2 تتأثر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top