sql >> Database teknologi >  >> RDS >> PostgreSQL

Forbindelsesproblemer med SQLAlchemy og flere processer

Citat "Hvordan bruger jeg motorer / forbindelser / sessioner med Python multiprocessing eller os.fork()?" med ekstra vægt:

SQLAlchemy Engine-objektet henviser til en forbindelsespulje af eksisterende databaseforbindelser. Så når dette objekt replikeres til en underordnet proces, er målet at sikre, at ingen databaseforbindelser overføres .

og

Men i tilfælde af, at en transaktionsaktiv session eller forbindelse deles, er der ingen automatisk løsning på dette; en applikation skal sikre, at en ny underordnet proces kun starter nye forbindelsesobjekter og -transaktioner samt ORM-sessionsobjekter.

Problemet stammer fra den forklede underordnede proces, der arver den live globale session , som holder på en forbindelse . Når mål kalder init , overskriver den de globale referencer til engine og session , hvilket reducerer deres gentællinger til 0 i barnet, hvilket tvinger dem til at afslutte. Hvis du for eksempel på den ene eller anden måde opretter en anden reference til den nedarvede session hos barnet, forhindrer du, at der bliver ryddet op – men det gør du ikke. Efter main har tilsluttet sig og vender tilbage til business as usual, forsøger den at bruge den nu potentielt afsluttede – eller på anden måde ude af synkronisering – forbindelse. Hvorfor dette kun forårsager en fejl efter nogle gentagelser er jeg ikke sikker på.

Den eneste måde at håndtere denne situation ved at bruge globals, som du gør, er at

  1. Luk alle sessioner
  2. Ring til engine.dispose()

før gaffel. Dette vil forhindre forbindelser i at lække til barnet. For eksempel:

def main():
    global session
    init()
    try:
        dummy = Dummy(value=1)
        session.add(dummy)
        session.commit()
        dummy_id = dummy.id
        # Return the Connection to the pool
        session.close()
        # Dispose of it!
        engine.dispose()
        # ...or call your cleanup() function, which does the same
        p = multiprocessing.Process(target=target, args=(dummy_id,))
        p.start()
        p.join()
        # Start a new session
        session = Session()
        dummy = session.query(Dummy).get(dummy_id)
        assert dummy.value == 2
    finally:
        cleanup()

Dit andet eksempel udløser ikke færdiggørelse i barnet, og det ser derfor kun ud til at virke, selvom det måske er lige så ødelagt som det første, da det stadig arver en kopi af sessionen og dens forbindelse defineret lokalt i main .




  1. Kom godt i gang med SQL Server 2017 på Linux i Azure-portalen

  2. SQL - Konverteringen af ​​en varchar-datatype til en datetime-datatype resulterede i en værdi uden for området

  3. Tabeltype i eksempel på Oracle Stored Procedure

  4. PHP PDO og MySQLi