ขอให้ไม่ใช้ธุรกรรมและใช้วิธีแก้ปัญหาเพื่อจำลองสถานการณ์หนึ่ง


43

ฉันได้พัฒนา T-SQL มาหลายปีแล้วและกำลังขุดอยู่เสมอและเรียนรู้ทุกอย่างที่เกี่ยวกับภาษาได้อย่างต่อเนื่อง ฉันเพิ่งเริ่มทำงานกับ บริษัท ใหม่และได้รับสิ่งที่ฉันคิดว่าเป็นข้อเสนอแนะแปลก ๆ เกี่ยวกับการทำธุรกรรม ไม่เคยใช้พวกเขา ใช้วิธีแก้ปัญหาที่จำลองธุรกรรมแทน นี่มาจาก DBA ของเราที่ทำงานในฐานข้อมูลเดียวกับธุรกรรมจำนวนมากและต่อมามีการบล็อกจำนวนมาก ฐานข้อมูลที่ฉันทำงานเป็นหลักไม่ประสบปัญหานี้และฉันเห็นว่ามีการใช้ธุรกรรมในอดีต

ฉันเข้าใจว่าการปิดกั้นเป็นสิ่งที่คาดว่าจะเกิดขึ้นเนื่องจากเป็นไปตามปกติของพวกเขาและถ้าคุณสามารถหลีกเลี่ยงได้โดยไม่ต้องใช้สิ่งใดสิ่งหนึ่ง แต่ฉันมีหลายครั้งที่แต่ละคำสั่งต้องทำงานสำเร็จ หากล้มเหลวพวกเขาทั้งหมดจะต้องล้มเหลวในการกระทำ

ฉันรักษาขอบเขตการทำธุรกรรมของฉันให้แคบที่สุดเสมอใช้ร่วมกับ SET XACT_ABORT ON เสมอและอยู่ในการทดลอง / จับ

ตัวอย่าง:

CREATE SCHEMA someschema;
GO


CREATE TABLE someschema.tableA
(id   INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, 
 ColA VARCHAR(10) NOT NULL
);
GO

CREATE TABLE someschema.tableB
(id   INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, 
 ColB VARCHAR(10) NOT NULL
); 
GO


CREATE PROCEDURE someschema.ProcedureName @ColA VARCHAR(10), 
                                          @ColB VARCHAR(10)
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN
BEGIN TRY
    BEGIN TRANSACTION;

    INSERT INTO someschema.tableA(ColA)
    VALUES(@ColA);

    INSERT INTO someschema.tableB(ColB)
    VALUES(@ColB);

--Implement error
    SELECT 1/0 

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF @@trancount > 0
    BEGIN
        ROLLBACK TRANSACTION;
    END;
    THROW;
    RETURN;
END CATCH;
END;
GO

นี่คือสิ่งที่พวกเขาแนะนำว่าฉันทำ

GO



CREATE PROCEDURE someschema.ProcedureNameNoTransaction @ColA VARCHAR(10), 
                                                       @ColB VARCHAR(10)
AS
SET NOCOUNT ON;
BEGIN
BEGIN TRY
    DECLARE @tableAid INT;
    DECLARE @tableBid INT;

    INSERT INTO someschema.tableA(ColA)
    VALUES(@ColA);
    SET @tableAid = SCOPE_IDENTITY();

    INSERT INTO someschema.tableB(ColB)
    VALUES(@ColB);
    SET @tableBid = SCOPE_IDENTITY();

--Implement error
    SELECT 1/0 

END TRY
BEGIN CATCH
    DELETE FROM someschema.tableA
    WHERE id = @tableAid;

    DELETE FROM someschema.tableB
    WHERE id = @tableBid;

    THROW;

    RETURN;
END CATCH;
END;
GO

คำถามของฉันที่มีต่อชุมชนมีดังนี้ สิ่งนี้สมเหตุสมผลหรือไม่ที่เป็นวิธีแก้ปัญหาสำหรับการทำธุรกรรม?

ความคิดเห็นของฉันจากสิ่งที่ฉันรู้เกี่ยวกับธุรกรรมและสิ่งที่วิธีแก้ปัญหาเสนอคือไม่นี่ไม่ใช่วิธีแก้ปัญหาที่ใช้การได้และแนะนำจุดล้มเหลวมากมาย

ในวิธีแก้ปัญหาที่แนะนำฉันเห็นสี่ธุรกรรมโดยนัยที่เกิดขึ้น ทั้งสองแทรกในการลองแล้วอีกสองธุรกรรมสำหรับการลบในการจับ มันจะ "เลิกทำ" เม็ดมีด แต่ไม่มีการย้อนกลับอะไรเลยดังนั้นจึงไม่มีสิ่งใดถูกย้อนกลับได้

นี่เป็นตัวอย่างพื้นฐานที่แสดงให้เห็นถึงแนวคิดที่พวกเขากำลังแนะนำ ขั้นตอนการจัดเก็บจริงบางอย่างที่ฉันทำนี้ทำให้พวกเขาใช้เวลานานและยากที่จะจัดการเพราะ "ย้อนกลับ" ชุดผลลัพธ์หลายรายการกับค่าพารามิเตอร์สองค่าในตัวอย่างนี้ค่อนข้างซับซ้อนอย่างที่คุณจินตนาการ เนื่องจาก "ย้อนกลับ" กำลังทำด้วยตนเองตอนนี้โอกาสที่จะพลาดบางสิ่งเพราะจริง

ปัญหาอื่นที่ฉันคิดว่ามีอยู่สำหรับการหมดเวลาหรือการเชื่อมต่อที่ตัดขาด สิ่งนี้ยังคงย้อนกลับได้ไหม? นี่คือความเข้าใจของฉันว่าทำไมควรใช้ SET XACT_ABORT ON เพื่อให้ในกรณีเหล่านี้ธุรกรรมจะย้อนกลับ

ขอบคุณสำหรับความคิดเห็นของคุณล่วงหน้า!


4
ความคิดเห็นที่ไม่ได้ให้บริการตามวัตถุประสงค์ที่ระบุไว้ถูกลบหรือย้ายไปยังคำตอบของ Community Wiki
พอลไวท์

คำตอบ:


61

คุณไม่สามารถไม่ใช้การทำธุรกรรมใน SQL Server (และอาจจะ RDBMS ใด ๆ ที่เหมาะสมอื่น ๆ ) ในกรณีที่ไม่มีขอบเขตการทำธุรกรรมที่ชัดเจน ( begin transaction... commit) แต่ละคำสั่ง SQL จะเริ่มทำธุรกรรมใหม่ซึ่งมีความมุ่งมั่นโดยปริยาย (หรือย้อนกลับ) หลังจากคำสั่งเสร็จสมบูรณ์ (หรือล้มเหลว)

การจำลองการทำธุรกรรมที่แนะนำโดยบุคคลที่แสดงตนด้วยตนเองในฐานะ "DBA" ของคุณล้มเหลวในการตรวจสอบคุณสมบัติสามอย่างจากการประมวลผลธุรกรรมที่ต้องการเนื่องจากสามข้อผิดพลาด "อ่อน" และไม่สามารถจัดการกับข้อผิดพลาด "ยาก" ได้ เช่นการตัดการเชื่อมต่อเครือข่ายไฟฟ้าขัดข้องความล้มเหลวของดิสก์และอื่น ๆ

  • Atomicity: ล้มเหลว หากมีข้อผิดพลาด "ยาก" เกิดขึ้นที่ใดที่หนึ่งในระหว่างการทำธุรกรรมหลอกของคุณการเปลี่ยนแปลงจะไม่ใช่อะตอมมิก

  • ความสอดคล้อง: ล้มเหลว ตามจากข้างต้นข้อมูลของคุณจะอยู่ในสถานะไม่สอดคล้องกันหลังจากข้อผิดพลาด "ยาก"

  • การแยก: ล้มเหลว เป็นไปได้ว่าธุรกรรมหลอกพร้อมกันจะเปลี่ยนแปลงข้อมูลบางส่วนที่แก้ไขโดยธุรกรรมหลอกของคุณก่อนที่คุณจะทำเสร็จ

  • ความทนทาน: สำเร็จ การเปลี่ยนแปลงที่คุณทำจะมีความคงทนเซิร์ฟเวอร์ฐานข้อมูลจะตรวจสอบให้แน่ใจว่า นี่เป็นสิ่งเดียวที่เพื่อนร่วมงานของคุณไม่สามารถทำพลาดได้

การล็อคเป็นวิธีที่ใช้กันอย่างแพร่หลายและประสบความสำเร็จในการยืนยันความเป็นกรดของการทำธุรกรรมในทุกประเภทหรือ RDBMSes (ไซต์นี้เป็นตัวอย่าง) ฉันคิดว่ามันไม่น่าเป็นไปได้ที่ DBA แบบสุ่มจะสามารถหาทางออกที่ดีกว่าสำหรับปัญหาการเกิดพร้อมกันมากกว่าร้อยคนอาจเป็นนักวิทยาศาสตร์คอมพิวเตอร์และวิศวกรหลายพันคนที่สร้างระบบฐานข้อมูลที่น่าสนใจในช่วง 50 ปี 60 ปี (ฉันรู้ว่านี่ค่อนข้างผิดพลาดเป็นข้อโต้แย้งเรื่อง "อุทธรณ์ต่อผู้มีอำนาจ" แต่ฉันจะยึดติดกับเรื่องนี้โดยไม่คำนึงถึง)

โดยสรุปอย่าเพิกเฉยคำแนะนำของ "DBA" ของคุณหากทำได้ต่อสู้กับมันหากคุณมีวิญญาณแล้วกลับมาที่นี่พร้อมกับปัญหาที่เกิดขึ้นพร้อมกันโดยเฉพาะถ้าเกิดขึ้น


14

มีข้อผิดพลาดบางอย่างซึ่งรุนแรงจนไม่สามารถป้อนบล็อก CATCH ได้ จากเอกสารประกอบ

ข้อผิดพลาดที่มีความรุนแรง 20 หรือสูงกว่าซึ่งหยุดการประมวลผลงาน SQL Server Database Engine สำหรับเซสชัน หากมีข้อผิดพลาดเกิดขึ้นที่มีความรุนแรง 20 หรือสูงกว่าและการเชื่อมต่อฐานข้อมูลจะไม่หยุดชะงัก TRY ... CATCH จะจัดการกับข้อผิดพลาด

ความสนใจเช่นการร้องขอการขัดจังหวะลูกค้าหรือการเชื่อมต่อไคลเอนต์ที่ใช้งานไม่ได้

เมื่อเซสชันสิ้นสุดลงโดยผู้ดูแลระบบโดยใช้คำสั่ง KILL

...

ข้อผิดพลาดในการคอมไพล์เช่นข้อผิดพลาดทางไวยากรณ์ที่ป้องกันไม่ให้ชุดงานทำงาน

ข้อผิดพลาดที่เกิดขึ้น ... เนื่องจากการแก้ไขชื่อที่เลื่อนออกไป

สิ่งเหล่านี้จำนวนมากผลิตง่ายผ่าน SQL แบบไดนามิก เลิกทำงบเช่นที่คุณแสดงจะไม่ปกป้องข้อมูลของคุณจากข้อผิดพลาดดังกล่าว


2
ถูกต้อง - และหากไม่มีสิ่งอื่นใดลูกค้ากำลังจะตายในขณะที่เรียกใช้งานรหัสจะถือเป็นข้อผิดพลาด "รุนแรงมากจนไม่ได้ป้อนบล็อก CATCH" ไม่ว่าคุณจะเชื่อถือซอฟต์แวร์มากแค่ไหน (ไม่ใช่แค่รหัสของคุณเอง แต่ยังเป็นส่วนหนึ่งของซอฟต์แวร์ทั้งหมดที่เกี่ยวข้อง) มีความเป็นไปได้ของความล้มเหลวของฮาร์ดแวร์ (อีกครั้งอาจเกิดขึ้นที่ใดก็ได้ในเครือ) หยุดคุณได้ทุกเวลา . การเก็บสิ่งนี้ไว้ในใจเป็นการป้องกันที่ดีต่อความคิดที่นำไปสู่ ​​"การแก้ปัญหา" ประเภทนี้
dgould

2
นอกจากนี้คุณอาจตกเป็นเหยื่อการหยุดชะงัก บล็อก CATCH ของคุณทำงาน แต่โยนหากพยายามเขียนไปยังฐานข้อมูล
Joshua

10

I-หนึ่ง : วิธีแก้ปัญหาที่จะแนะนำให้คุณทำให้เป็นไปได้ (อย่างน้อย) ละเมิด "A" ของกรด ตัวอย่างเช่นหาก SP ถูกดำเนินการโดยไคลเอนต์ระยะไกลและการเชื่อมต่อการหยุดพักดังนั้นบางส่วน "กระทำ" / "ย้อนกลับ" อาจเกิดขึ้นเพราะเซิร์ฟเวอร์สามารถยุติเซสชันระหว่างการแทรก / การลบสองครั้ง (และยกเลิกการดำเนินการ SP ก่อนที่จะสิ้นสุด) .

สิ่งนี้สมเหตุสมผลหรือไม่ที่เป็นวิธีแก้ปัญหาสำหรับการทำธุรกรรม?

dan-guzman : ไม่CATCHบล็อกไม่เคยถูกเรียกใช้งานในกรณีของการหมดเวลาของการสืบค้นเนื่องจากไคลเอ็นต์ API ยกเลิกแบตช์ หากไม่มีธุรกรรมSET XACT_ABORT ONไม่สามารถย้อนกลับสิ่งอื่นนอกเหนือจากคำสั่งปัจจุบัน

tibor-karaszi : คุณมี 4 ธุรกรรมหมายถึงการบันทึกเพิ่มเติมไปยังไฟล์บันทึกธุรกรรม โปรดจำไว้ว่าแต่ละธุรกรรมต้องมีการเขียนบันทึกบันทึกแบบซิงโครนัสจนถึงจุดนั้นเช่นคุณจะได้รับประสิทธิภาพที่แย่ลงจากแง่มุมนั้นเมื่อใช้หลายธุรกรรม

rbarryyoung : หากพวกเขาได้รับการบล็อคจำนวนมากพวกเขาจำเป็นต้องแก้ไขการออกแบบข้อมูล, หาเหตุผลเข้าข้างตนเองเพื่อเข้าถึงตารางหรือใช้ระดับการแยกที่เหมาะสมยิ่งขึ้น พวกเขาสมมติว่าปัญหาของพวกเขา (และไม่เข้าใจ) จะกลายเป็นปัญหาของคุณ หลักฐานจากฐานข้อมูลอื่น ๆ นับล้านคือมันจะไม่

นอกจากนี้สิ่งที่พวกเขากำลังพยายามที่จะใช้งานด้วยตนเองก็คือการเห็นพ้องด้วยมองโลกในแง่ดีในแง่ดี สิ่งที่พวกเขาควรทำคือการใช้การมองโลกในแง่ดีที่สุดในโลกพร้อมกันใน SQL Server สิ่งนี้จะไปยังจุดแยกด้านบน ในทุกโอกาสที่พวกเขาจะต้องเปลี่ยนจากสิ่งที่มองโลกในแง่ระดับเห็นพ้องด้วยการแยกพวกเขากำลังใช้ให้เป็นหนึ่งในระดับเห็นพ้องด้วยการแยกในแง่ดี หรือSNAPSHOT READ_COMMITTED_SNAPSHOTสิ่งเหล่านี้จะทำสิ่งเดียวกับรหัสคู่มืออย่างมีประสิทธิภาพยกเว้นว่าจะทำอย่างถูกต้อง

Ross-Presser : ถ้าคุณได้ยาวนานมากกระบวนการทำงานที่ชอบ - สิ่งที่เกิดขึ้นในวันนี้และบางสิ่งบางอย่างในสัปดาห์หน้ามีการติดตามและถ้าสิ่งที่สัปดาห์ถัดไปล้มเหลวแล้ววันนี้มีการล้มเหลวย้อนหลัง - คุณอาจต้องการที่จะดูเป็นโศกนาฏกรรม การพูดอย่างเคร่งครัดนี้อยู่นอกฐานข้อมูลเนื่องจากต้องใช้บริการบัส


5

รหัสความคิดที่ไม่ดีจะมีราคาแพงกว่าในการแก้ไขปัญหา

หากมีปัญหาในการบล็อกโดยใช้การทำธุรกรรมอย่างชัดเจน (ย้อนกลับ / ส่ง) ให้ชี้ DBA ของคุณไปยังอินเทอร์เน็ตเพื่อหาแนวคิดที่ดีในการแก้ไขปัญหา

นี่คือวิธีที่จะช่วยบรรเทาการบล็อก: https://www.sqlservercentral.com/articles/using-indexes-to-reduce-blocking-in-concurrent-transactions

ดัชนีลดจำนวนการค้นหาที่ต้องเกิดขึ้นในตาราง / หน้าเพื่อค้นหาแถว / ชุดของแถว โดยทั่วไปแล้วพวกเขาจะถูกมองว่าเป็นวิธีการลดเวลาดำเนินการสำหรับแบบสอบถาม SELECT * และถูกต้องเช่นกัน พวกเขาจะไม่ถือว่าเหมาะสมสำหรับตารางที่เกี่ยวข้องในการปรับปรุงจำนวนมาก ในความเป็นจริงแล้ว INDEXES นั้นพบว่าไม่เอื้ออำนวยในกรณีเหล่านี้เนื่องจากจะเพิ่มเวลาในการสืบค้น UPDATE ให้สมบูรณ์

แต่นี่ไม่ใช่กรณีเสมอไป การขุดลึกลงไปเล็กน้อยในการดำเนินการคำสั่ง UPDATE เราพบว่ามันเกี่ยวข้องกับการดำเนินการคำสั่ง SELECT ก่อนเช่นกัน นี่เป็นสถานการณ์พิเศษและที่มักพบเห็นได้ซึ่งคิวรีจะอัปเดตชุดของแถวที่ไม่เกิดร่วมกัน ดัชนีที่นี่สามารถนำไปสู่การเพิ่มขึ้นอย่างมีนัยสำคัญในการทำงานของเครื่องมือฐานข้อมูลตรงกันข้ามกับความเชื่อที่นิยม


4

กลยุทธ์การทำธุรกรรมปลอมนั้นเป็นสิ่งที่อันตรายเพราะจะช่วยให้เกิดปัญหาที่เกิดขึ้นพร้อมกันที่การทำธุรกรรมป้องกันโดยเฉพาะ พิจารณาว่าในตัวอย่างที่สองข้อมูลใด ๆ อาจมีการเปลี่ยนแปลงระหว่างคำสั่ง

การลบธุรกรรมปลอมไม่ได้รับประกันว่าจะทำงานได้หรือประสบความสำเร็จ หากเซิร์ฟเวอร์ฐานข้อมูลปิดระหว่างการทำธุรกรรมปลอมเอฟเฟกต์บางอย่าง แต่ไม่ใช่ทั้งหมดจะยังคงอยู่ พวกเขายังไม่รับประกันว่าจะประสบความสำเร็จในทางพูดว่าการทำธุรกรรมย้อนกลับเป็น

กลยุทธ์นี้อาจใช้งานกับส่วนแทรกได้ แต่แน่นอนว่าจะไม่ทำงานกับการอัปเดตหรือการลบ (ไม่มีคำสั่ง SQL ของ Time Machine)

หากการทำรายการพร้อมกันที่เข้มงวดทำให้การปิดกั้นมีวิธีแก้ไขมากมายแม้กระทั่งวิธีที่ลดระดับการป้องกัน ... นี่เป็นวิธีที่ถูกต้องในการแก้ปัญหา

DBA ของคุณกำลังเสนอโซลูชันที่อาจใช้งานได้หากมีผู้ใช้เพียงรายเดียวของฐานข้อมูล แต่ไม่เหมาะสำหรับการใช้งานประเภทใด


4

นี่ไม่ใช่ปัญหาการเขียนโปรแกรม แต่เป็นปัญหาระหว่างบุคคล / การสื่อสารผิดพลาด เป็นไปได้มากว่า "DBA" ของคุณเป็นกังวลเกี่ยวกับการล็อคไม่ใช่ธุรกรรม

คำตอบอื่น ๆ แล้วอธิบายว่าทำไมคุณต้องใช้การทำธุรกรรม ... ฉันหมายความว่านั่นคือสิ่งที่ RDBMS ทำโดยไม่ต้องใช้การทำธุรกรรมอย่างถูกต้องไม่มีความสมบูรณ์ของข้อมูลดังนั้นฉันจะมุ่งเน้นไปที่วิธีแก้ปัญหาจริงซึ่งก็คือ: ค้นหาสาเหตุ "DBA" ของคุณพัฒนาแพ้การทำธุรกรรมและโน้มน้าวให้เขาเปลี่ยนใจ

ฉันคิดว่าผู้ชายคนนี้สับสน "สถานการณ์เฉพาะที่โค้ดไม่ดีส่งผลให้ประสิทธิภาพแย่" กับ "ธุรกรรมทั้งหมดไม่ดี" ฉันไม่คาดหวังว่า DBA ที่มีความสามารถจะทำผิดพลาดนั่นจึงแปลกจริง ๆ บางทีเขาอาจมีประสบการณ์ที่ไม่ดีกับรหัสที่แย่มาก?

พิจารณาสถานการณ์เช่นนี้:

BEGIN
UPDATE or DELETE some row, which takes locks it
...do something that takes a while
...perform other queries
COMMIT

การใช้รูปแบบการทำธุรกรรมนี้มีการล็อค (หรือล็อคหลายครั้ง) ซึ่งหมายความว่าการทำธุรกรรมอื่น ๆ ที่กดปุ่มแถวเดียวกันจะต้องรอ ถ้าล็อคถูกเก็บไว้เป็นเวลานานและโดยเฉพาะอย่างยิ่งถ้าธุรกรรมอื่น ๆ จำนวนมากต้องการล็อคแถวเดียวกันนี้อาจส่งผลกระทบต่อประสิทธิภาพการทำงาน

สิ่งที่คุณสามารถทำได้คือถามเขาว่าทำไมเขาถึงมีความคิดผิด ๆ ที่อยากรู้อยากเห็นไม่ใช้ธุรกรรมประเภทของการสืบค้นมีปัญหา ฯลฯ จากนั้นลองชักชวนให้เขารู้ว่าคุณจะหลีกเลี่ยงสถานการณ์เลวร้ายที่คล้ายกัน การแสดงมั่นใจกับเขา ฯลฯ

สิ่งที่เขาบอกคุณคือ "อย่าแตะไขควง!" ดังนั้นรหัสที่คุณโพสต์ในคำถามของคุณนั้นใช้ค้อนเพื่อขับสกรู ตัวเลือกที่ดีกว่าคือการโน้มน้าวให้เขารู้วิธีใช้ไขควง ...

ฉันสามารถนึกถึงหลายตัวอย่าง ... ดีพวกเขาอยู่ใน MySQL แต่ที่ควรจะทำงานด้วย

มีฟอรัมที่ดัชนีข้อความแบบเต็มใช้เวลาในการอัปเดต เมื่อผู้ใช้ส่งโพสต์การทำธุรกรรมจะปรับปรุงตารางหัวข้อเพื่อเพิ่มจำนวนการโพสต์และวันที่โพสต์ล่าสุด (เช่นการล็อคแถวหัวข้อ) จากนั้นแทรกการโพสต์และการทำธุรกรรมจะระงับการล็อคจนกว่าดัชนี fulltext เสร็จสิ้นการอัปเดต และคอมมิชชันก็ทำ

เนื่องจากสิ่งนี้วิ่งบนถังเก็บสนิมที่มี RAM น้อยเกินไปการอัปเดตกล่าวว่าดัชนี fulltext มักจะส่งผลให้เกิดการสุ่ม IO ที่รุนแรงในหลายวินาทีบนไดรฟ์หมุนช้าเดียวในกล่อง

ปัญหาคือคนที่คลิกที่หัวข้อทำให้เกิดการสอบถามเพื่อเพิ่มจำนวนการดูในหัวข้อซึ่งจำเป็นต้องล็อคในแถวหัวข้อด้วย ดังนั้นจึงไม่มีใครสามารถดูหัวข้อในขณะที่ดัชนี fulltext กำลังอัปเดต ฉันหมายถึงแถวสามารถอ่านได้ แต่การอัพเดทมันจะล็อค

ยิ่งแย่กว่านั้นการโพสต์จะอัปเดตการนับโพสต์บนตารางฟอรัมหลักและยังล็อคไว้ในขณะที่ดัชนี fulltext กำลังอัปเดต ... ซึ่งทำให้ทั้งฟอรัมทั้งหมดค้างคืนในไม่กี่วินาทีและทำให้มีคำขอจำนวนมากในคิวเว็บเซิร์ฟเวอร์ .

วิธีแก้ไขคือทำการล็อคตามลำดับที่ถูกต้อง: BEGIN แทรกการโพสต์และอัพเดตดัชนี fulltext โดยไม่ทำการล็อคใด ๆ จากนั้นอัพเดตแถวหัวข้อ / ฟอรัมอย่างรวดเร็วด้วยการนับจำนวนโพสต์และวันที่โพสต์ล่าสุดและ COMMIT นั่นเป็นการแก้ไขปัญหาอย่างสมบูรณ์ มันเป็นเพียงการเคลื่อนที่ไปรอบ ๆ แบบสอบถามไม่กี่ง่ายๆจริงๆ

ในกรณีนี้การทำธุรกรรมไม่ใช่ปัญหา ... มันได้รับการล็อคที่ไม่จำเป็นก่อนการดำเนินการที่ยาวนาน ตัวอย่างอื่น ๆ ของสิ่งที่ต้องหลีกเลี่ยงในขณะที่ล็อคการทำธุรกรรม: รอการป้อนข้อมูลของผู้ใช้เข้าถึงข้อมูลที่ไม่ได้เก็บข้อมูลจำนวนมากจากไดรฟ์ที่หมุนช้าเครือข่าย IO ฯลฯ

แน่นอนว่าบางครั้งคุณไม่มีทางเลือกและคุณต้องทำการประมวลผลที่ยาวนานในขณะที่ถือกุญแจที่ยุ่งยาก มีเคล็ดลับเกี่ยวกับเรื่องนี้ (ทำงานกับสำเนาของข้อมูล ฯลฯ ) แต่บ่อยครั้งที่คอขวดของประสิทธิภาพมาจากการล็อกที่ไม่ได้รับมาโดยเจตนาและการเรียงลำดับคิวรีใหม่จะช่วยแก้ปัญหาได้ ยิ่งไปกว่านั้นการรับรู้ถึงการล็อคที่ใช้ในขณะที่เขียนแบบสอบถาม ...

ฉันจะไม่ทำซ้ำคำตอบอื่น ๆ แต่จริงๆแล้ว ... ใช้ธุรกรรม ปัญหาของคุณกำลังโน้มน้าวใจ "DBA" ของคุณไม่ทำงานกับคุณสมบัติที่สำคัญที่สุดของฐานข้อมูล ...


3

TLDR:การใช้งานที่เหมาะสมระดับแยก

ในขณะที่คุณสังเกตเห็นวิธีการอย่างถูกต้องโดยไม่มีการทำธุรกรรมและด้วยการกู้คืน "ด้วยตนเอง" อาจซับซ้อนมาก ความซับซ้อนสูงหมายถึงโดยปกติแล้วเวลาในการปรับใช้และเวลาในการแก้ไขข้อผิดพลาด (เนื่องจากความซับซ้อนนำไปสู่ข้อผิดพลาดเพิ่มเติมในการใช้งาน) หมายความว่าวิธีการดังกล่าวสามารถทำให้ลูกค้าของคุณมีค่าใช้จ่ายมากขึ้น

ข้อกังวลหลักของเพื่อนร่วมงาน "dba" คือประสิทธิภาพ อีกวิธีหนึ่งในการปรับปรุงคือการใช้ระดับการแยกที่เหมาะสม สมมติว่าคุณมีโพรซีเดอร์ที่ให้ข้อมูลภาพรวมบางชนิดแก่ผู้ใช้ ขั้นตอนดังกล่าวไม่จำเป็นต้องใช้ระดับการแยกแบบ SERIALIZABLE ในหลายกรณีการอ่าน UNCOMMITTED นั้นค่อนข้างเพียงพอ หมายความว่าขั้นตอนดังกล่าวจะไม่ถูกบล็อกโดยการทำธุรกรรมของคุณที่สร้างหรือแก้ไขข้อมูลบางอย่าง

ฉันขอแนะนำให้คุณตรวจสอบฟังก์ชั่น / ขั้นตอนที่มีอยู่ทั้งหมดในฐานข้อมูลของคุณประเมินระดับการแยกที่เหมาะสมสำหรับแต่ละรายการอธิบายประโยชน์ที่ลูกค้าจะได้รับ จากนั้นปรับฟังก์ชั่น / ขั้นตอนเหล่านี้ให้เหมาะสม


2

คุณสามารถตัดสินใจที่จะใช้ตาราง OLTP ในหน่วยความจำ แน่นอนว่าพวกเขายังใช้ธุรกรรม แต่ไม่มีการบล็อกที่เกี่ยวข้อง
แทนที่จะปิดกั้นการดำเนินการทั้งหมดจะประสบความสำเร็จ แต่ในระหว่างขั้นตอนการกำหนดกลไกจะตรวจสอบความขัดแย้งของการทำธุรกรรมและหนึ่งในข้อผูกพันอาจล้มเหลว Microsoft ใช้คำว่า "การล็อคในแง่ดี"
หากปัญหาการปรับขนาดเกิดจากความขัดแย้งระหว่างการดำเนินการเขียนสองครั้งเช่นธุรกรรมที่เกิดขึ้นพร้อมกันสองรายการที่พยายามอัปเดตแถวเดียวกัน In-Memory OLTP ทำให้ธุรกรรมหนึ่งสำเร็จและล้มเหลวในการทำธุรกรรมอื่น ธุรกรรมที่ล้มเหลวจะต้องส่งอีกครั้งอย่างชัดเจนหรือโดยนัยลองทำธุรกรรมอีกครั้ง
เพิ่มเติมได้ที่: ในหน่วยความจำ OLTP


-5

มีวิธีการใช้ธุรกรรมในขอบเขตที่ จำกัด และนั่นคือโดยการเปลี่ยนรูปแบบข้อมูลของคุณให้เป็นเชิงวัตถุมากขึ้น ดังนั้นแทนที่จะเก็บตัวอย่างข้อมูลประชากรเกี่ยวกับบุคคลในหลายตารางและเกี่ยวข้องกันและต้องการธุรกรรมคุณสามารถมีเอกสาร JSON เดียวที่เก็บทุกสิ่งที่คุณรู้จักเกี่ยวกับบุคคลนั้นในฟิลด์เดียว แน่นอนว่าการขยายขอบเขตของโดเมนนั้นเป็นความท้าทายด้านการออกแบบอีกประการหนึ่งซึ่งทำได้โดยนักพัฒนาไม่ใช่ DBA

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.