จะเชื่อมต่อกับ UIBDatabase + UIBTransaction เดียวกันอีกครั้งหลังจากเครือข่ายสูญหายได้อย่างไร

เรามีแอปพลิเคชัน Delphi7 + UIB + Firebird 2.5 สำหรับร้านพิซซ่า ซึ่งทำงานได้เสถียรบนเครือข่ายแบบมีสาย
แต่เมื่อใช้ wifi (ทำงานร่วมกับแท็บเล็ตพีซี Win8/Win10) หากการเชื่อมต่อขาดหาย UIBDatabase ไม่สามารถเชื่อมต่อใหม่ได้โดยอัตโนมัติ

(ขณะนี้เรากำลังสร้างแอปทั้งหมดใหม่เพื่อลบ "IBX ที่เหลือ" แต่หลังจากอัปเกรด UIB เป็นเวอร์ชันล่าสุด ดูเหมือนว่าปัญหาจะยิ่งแย่ลงไปอีก!)

หลังจากการเชื่อมต่อขาดหาย ข้อความแสดงข้อผิดพลาด เป็น:

Project ...exe raised exception class EUIBError with message 'connection rejected by remote interface
Connection not established
GDS Code: 335544421 - SQL Code: -923 - Error Code: 101'. Process stopped. 

แม้ว่าฉันพยายามปิดการเชื่อมต่อปัจจุบันด้วย .IsConnected:=False หรือ .CancelAbort ก็ไม่สามารถเชื่อมต่อใหม่ได้อีก:

Project ...exe raised exception class EUIBError with message 'invalid statement handle
Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements
GDS Code: 335544485 - SQL Code: -901 - Error Code: 165'. Process stopped. Use Step or Run to continue.

ดังนั้นไม่ว่าเราจะทำอะไร เราไม่สามารถเชื่อมต่อใหม่ได้!

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

เราได้พยายามเริ่ม TTimer ก่อนเพื่อบังคับให้ยกเลิกการดำเนินการหลังจาก 2000 มิลลิวินาที แต่เหตุการณ์นั้นไม่เคยถูกไล่ออก

ฉันจึงสงสัยว่า:

  • มีวิธีจัดการกรณีเหล่านี้อย่างเหมาะสมหรือไม่?
  • ไม่มีใครมีปัญหาเช่นนี้? (สีแดง ทุกหัวข้อที่เกี่ยวข้องที่นี่ พบ เพียง 1 รายการที่คล้ายกัน พร้อมโซลูชัน 0 รายการ .)
  • องค์ประกอบ UIB ปัจจุบันสามารถดาวน์โหลดได้จาก ที่นี่ ไม่ เสถียร? (มีช่วงเวลาที่ยากลำบากในการคอมไพล์ภายใต้ D7 เนื่องจากมีข้อผิดพลาดที่ไม่เข้ากันของ SynEdit มากมาย!)
  • เหตุใดเหตุการณ์ .OnConnectionLoss จึงเริ่มทำงาน หลังจาก ฉันพยายามเชื่อมต่อใหม่อีกครั้งเท่านั้น
  • เป็นไปได้หรือไม่ที่จะเชื่อมต่อกับ:
    ธุรกรรม SAME อีกครั้ง,
    เสร็จสิ้นการค้นหา
    และยอมรับและปิดอย่างถูกต้อง?
    (เนื่องจากเราสามารถอ่านธุรกรรมได้ ID จาก Firebird) ... ดังนั้นเซิร์ฟเวอร์จึงไม่จำเป็นต้องเปิดค้างไว้นานกว่า 2 ชั่วโมง

person SzakiLaci    schedule 07.09.2019    source แหล่งที่มา
comment
หากคุณกำลังทำทุกอย่างใหม่ คุณควรพิจารณาการเชื่อมต่อแบบไร้สถานะ เช่น REST อย่างจริงจัง   -  person Jerry Dodge    schedule 07.09.2019
comment
ตามที่ฉันได้เขียนไว้: เรากำลังสร้าง IBX แบบเก่าที่เชื่อมต่อแบบไม่หยุดนิ่งขึ้นมาใหม่ให้เป็นแบบใหม่ ตอนนี้มันทำงานได้ไม่เสถียรเลย ฉันกำลังเชื่อมต่อ เพื่อตรวจสอบการเปลี่ยนแปลงเท่านั้น หลังจากได้รับ เหตุการณ์ FB เท่านั้น ข้อมูลทั้งหมดที่จัดเก็บไว้ในหน่วยความจำโดยใช้ตัวแปรที่ปลอดภัยสำหรับเธรด   -  person SzakiLaci    schedule 07.09.2019
comment
@JerryDodge ‹OFF› เราได้พยายามพัฒนาแอปมือถือ REST api + ในรอบเอว 4 ปีและหลายล้าน ลงถังขยะไปหมดแล้ว ไม่มีอีกแล้ว เราต้องการวิธีแก้ไขปัญหาข้างต้น ‹/OFF›   -  person SzakiLaci    schedule 07.09.2019
comment
ถ้าฉันอยู่ในสถานการณ์ของคุณ ฉันถามตัวเองว่าฉันจะทำอย่างไร? สิ่งแรกที่ฉันจะทำคือเปลี่ยนส่วนประกอบฐานข้อมูลของฉัน ใน Delphi 7 คุณมีตัวเลือกในการใช้ IBX หรือ DBX กับไดรเวอร์ Upscene Productions Firebird (คุณสามารถหามันได้จากเครื่องเวย์แบ็ก)   -  person nolaspeaker    schedule 07.09.2019


คำตอบ (1)


ข้อผิดพลาด 1:
พิมพ์ tpConsistency แทน tpConcurrency โดยไม่ได้ตั้งใจที่ตำแหน่ง 1 ที่ประมาณ 50
LOCK นั้นแก้ไขทั้งตาราง ดังนั้นจึงไม่สามารถเชื่อมต่อกลับได้

ข้อผิดพลาด 2:
แนะนำให้ตั้งค่า myTransaction.DefaultAction := etmRollback;

ข้อผิดพลาด 3:

รหัส UIB ผิดที่ uiblib.pas

  • ตัวแปร FLockTimeout และ LockTimeout ต้องเป็นจำนวนเต็ม!
  • รหัสพารามิเตอร์คงที่:
    function CreateTRParams(Options: TTransParams; const LockRead, LockWrite: string{$IFDEF FB20_UP}; LockTimeout: integer{$ENDIF}): RawByteString;
    ...
      begin
      {$IFDEF FB20_UP}
      if LockTimeout = 0 then
          Exclude(Options, tpLockTimeout)
      else begin // -1 = infinite,   1..2048M = seconds
          Exclude(Options, tpnoWait);
          Include(Options, tpWait );
          Include(Options, tpLockTimeout);
      end;
      {$ENDIF}
      if Options = [tpConcurrency,tpWait,tpWrite] then
        result := ''
      else
        begin
          Result := isc_tpb_version3;
          for tp := Low(TTransParam) to High(TTransParam) do
            if (tp in Options) then
            begin
              case tp of
                tpLockRead   : ParseStrOption(tpc[tp], AnsiString(LockRead));
                tpLockWrite   : ParseStrOption(tpc[tp], AnsiString(LockWrite));
              {$IFDEF FB20_UP}
                tpLockTimeout : 
    //old code: PAnsiChar(@LockTimeout)[0] + PAnsiChar(LockTimeout)[1]; << [1] causing AV error
                  case LockTimeout of
                    -1     : Result := Result + tpc[tp] + #4#127#255#255#255;
    //               0     : Result := Result + tpc[tp] + #1#0; // this would be invalid
                    1..255: Result := Result + tpc[tp] + #1 + AnsiChar(Byte( LockTimeout and $FF));
                  else //256..32k
                            Result := Result + tpc[tp] + #2 + AnsiChar(Byte((LockTimeout div $FF) and $FF)) + AnsiChar(Byte(LockTimeout and $FF));
                  end;
              {$ENDIF}
              else
                Result := Result + tpc[tp];
              end;
            end;
        end;
    end;

คำขอคุณลักษณะ 4
ไม่พบวิธีแก้ปัญหาใดๆ เพื่อเชื่อมต่อกับธุรกรรม SAME ที่สูญหายไปก่อนหน้านี้อีกครั้ง

person SzakiLaci    schedule 10.09.2019
comment
คุณจะไม่สามารถเชื่อมต่อธุรกรรม SAME ที่สูญเสียไปก่อนหน้านี้ได้อีกครั้ง เนื่องจาก Firebird จะตรวจจับการเชื่อมต่อที่สูญหายและยุติธุรกรรม คุณต้องเชื่อมต่อใหม่และเปิดธุรกรรมใหม่ เท่าที่ฉันสามารถเข้าใจได้ว่าคุณกำลังใช้ธุรกรรมที่ใช้เวลานาน นี่เป็นข้อบกพร่องด้านการออกแบบที่ร้ายแรง ธุรกรรมของคุณควรสั้นที่สุดเท่าที่จะทำได้ - person ZeDalaye; 26.09.2019