Oracle - วิธีดูการเปลี่ยนแปลงที่ไม่ได้ตั้งใจบนตารางใด ๆ


24

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

ตัวอย่าง:

Insert into table myTable (col1, col2) values ("col1", "col2");

--Somehow view the pending transaction maybe by system view?....

...other DML statements....

commit;

มีมากกว่าหนึ่งวิธีที่จะทำ ตัวอย่างเช่นคำสั่ง SQL ที่นี่สามารถแก้ปัญหา: ducquoc.wordpress.com/2012/07/14/oracle-uncommited-changes ขอให้โชคดี

คำตอบ:


18

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

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

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

3) หากคุณเพียงแค่พยายามที่จะเห็นสถานะของกระบวนการแบทช์แทนที่จะเห็นข้อมูลจริงกระบวนการแบทช์สามารถเขียนข้อมูลการบันทึกโดยใช้ธุรกรรมอัตโนมัติที่คุณสามารถสอบถามได้จากเซสชันอื่น หรือคุณสามารถใช้แพ็คเกจ DBMS_APPLICATION_INFOเพื่อให้แอปพลิเคชันของคุณอัปเดตแอตทริบิวต์ต่างๆใน V $ SESSION และ / หรือ V $ SESSION_LONGOPS เพื่อให้คุณสามารถตรวจสอบสถานะของการโหลดจากเซสชันอื่น


10

แก้ไข: ถูกเขียนก่อนที่คำถามจะได้รับการชี้แจง

คุณสามารถใช้คำสั่งย้อนหลังเพื่อดูตารางโดยไม่ต้องของคุณเองข้อมูล uncommited

พิจารณา:

SQL> CREATE TABLE my_table
  2  AS SELECT ROWNUM ID FROM dual CONNECT BY LEVEL <= 5;

Table created

SQL> INSERT INTO my_table VALUES (6);

1 row inserted

หากต้องการดูความแตกต่างระหว่างตารางกับธุรกรรมของฉันและตารางตามที่ผู้อื่นเห็นฉันสามารถออก:

SQL> SELECT * FROM my_table
  2  MINUS
  3  SELECT * FROM my_table AS OF TIMESTAMP (systimestamp);

        ID
----------
         6

2
@jack: ยังไม่ชัดเจนถ้า OP ต้องการเห็นข้อมูลที่ไม่ได้รับการติดต่อนอกเซสชัน (สคริปต์หลอกอาจอยู่ในเซสชันเดียว) คำตอบของฉันจะทำงานเพื่อดูการแก้ไขที่รอดำเนินการของตัวเองในตารางเท่านั้น
Vincent Malgrat

คุณพูดถูก คำตอบที่ดี
Jack Douglas

8

ใช่ - LogMinerสามารถทำได้ ในความเป็นจริงถ้าคุณต้องการทำธุรกรรมที่มุ่งมั่นคุณจะต้องกรองผลลัพธ์โดยเฉพาะ! และมีTABLE_NAMEในV$LOGMINER_CONTENTSว่าเป็นวิธีที่คุณจะมองไปที่ตารางเดียว


8

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

มีวิธีในการรับข้อมูลจากธุรกรรมที่ใช้เวลานาน - สิ่งที่ไม่ได้กล่าวถึงคือธุรกรรมที่เป็นอิสระ (ซึ่งควรใช้ด้วยความระมัดระวัง)


5

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

ส่วนตัวผมขอแนะนำให้ใช้ธุรกรรมอัตโนมัติเพื่อเปิดใช้งานคุณสมบัตินี้ - ไม่ใช่ในการทำธุรกรรม แต่เป็นกลไกการบันทึกที่แจ้งให้คุณทราบว่าเกิดอะไรขึ้น ตัวอย่างเช่นคุณอาจมี PROCEDURE LONG_ACTION โทร PROCEDURE WRITE_LOG_ENTRY (กำหนดเป็นธุรกรรมอัตโนมัติ) ที่จะเขียน VARCHAR2 ไปยังตารางอื่น ธุรกรรมอิสระไม่รบกวนธุรกรรมปัจจุบันของคุณ (จากมุมมองเชิงตรรกะระวังผลกระทบที่อาจเกิดขึ้นกับประสิทธิภาพการทำงาน) และเพื่อให้คุณสามารถเห็นสิ่งที่เกิดขึ้นผ่านรายการบันทึกของคุณโดยไม่คำนึงถึง COMMIT หรือ ROLLBACK ในธุรกรรมปัจจุบันของคุณ ที่กล่าวว่าคุณสามารถทำได้ด้วยคำสั่ง DML ขนาดใหญ่; คุณต้องใช้การวนซ้ำ

พิจารณา:

TABLE LOG_ENTRIES defined as
    activity_date  date,
    log_entry varchar2(2000)

TABLE BIG_JOB (definition doesn't really matter)

PROCEDURE WRITE_LOG_ENTRY
                        ( str VARCHAR2 )
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO LOG_ENTRIES VALUES ( SYSDATE, str );
    COMMIT;
END;

PROCEDURE LONG_ACTION IS
    c NUMBER;
BEGIN
    FOR r IN ( SELECT * FROM BIG_JOB )
    LOOP
       c := c + 1;
       UPDATE BIG_JOB z
          SET fld = hairy_calculation
        WHERE z.rowid = r.rowid;
       IF MOD(c,500) = 0 THEN
           WRITE_LOG_ENTRY ( c || ' rows processed.' );
       END IF;
    END LOOP;
    COMMIT;
END;

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

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

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


1
คำเตือนในตอนท้ายของคำแนะนำนี้มีการสำรวจเพิ่มเติมในการตอบสนองของฉันยาว (มีรหัส) ที่orawin.info/blog/2011/09/06/advice-from-the-internet ในระยะสั้นการใช้วิธีการนี้อาจส่งผลกระทบร้ายแรงและรหัสที่ช้าแล้ว
Niall Litchfield

1
@ Niall Litchfield เช่นเคยเมื่อรับคำแนะนำจากอินเทอร์เน็ตเราควรทดสอบทดสอบและทดสอบทุกครั้ง เมื่อกล่าวถึงว่าการทำธุรกรรมอัตโนมัตินั้นไม่มีผลต่อการทำธุรกรรมฉันหมายถึงความจริงที่ว่ามันไม่ได้เป็นการกระทำหรือการย้อนกลับการทำธุรกรรมปัจจุบันของคุณ ดังนั้นในแง่ตรรกะมันไม่ทำอะไรกับการทำธุรกรรมปัจจุบันของคุณ ใช่แน่นอน Oracle ได้ทำสิ่งต่าง ๆ ไว้เบื้องหลังเพื่อให้สิ่งต่าง ๆ ทำงานได้ซึ่งอาจหมายถึงปัญหาด้านประสิทธิภาพจากมุมมองเฉพาะทรานแซกชันทรานแซคชันแบบอิสระจะไม่เข้าสู่สถานะของธุรกรรมปัจจุบันของฉัน
Kerri Shotts

@Niall Litchfield ทุกสิ่งที่กล่าวว่าการทำธุรกรรมด้วยตนเองมีปัญหาร่วมกันของตัวเอง (หนึ่งในนั้นเกิดขึ้นเพราะผู้คนพยายามที่จะใช้พวกเขาเพื่อหลีกเลี่ยงตารางกลายพันธุ์) ดังนั้นฉันขอแนะนำพวกเขาอย่างระมัดระวังและอย่างระมัดระวังเท่านั้น ด้วยความเข้าใจว่าเกิดอะไรขึ้น
Kerri Shotts

3

ไม่พร้อมใช้งานใน 10g แต่DBMS_XAสามารถอนุญาตให้ธุรกรรมข้ามเซสชันหลายเซสชันได้ เมื่อใช้เซสชันที่สองจะเห็นว่าเกิดอะไรขึ้นในธุรกรรม


3

นอกเหนือจากข้อมูลอื่น ๆ ที่นี่วิธีการเพิ่มเติมในการส่งข้อมูลเกี่ยวกับการทำธุรกรรมที่ไม่มีข้อผูกมัดคือการส่งอีเมลหรือเขียนไปยังไฟล์ข้อความ

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