SQL Alchemy session.commit และพฤติกรรมการฟลัช

ฉันกำลังทำงานกับฐานโค้ดขนาดใหญ่โดยใช้ SQL Alchemy เราเพิ่งเปลี่ยนเป็น structlog สำหรับการบันทึก และพฤติกรรมของ SQLAlchemy เปลี่ยนไป ในฟังก์ชันที่มีการแทรกข้อมูลลงใน MySQL หากการเรียก session.commit() อยู่ก่อนคำสั่งบันทึกและไม่ได้อยู่ในส่วนคำสั่งสุดท้าย อ็อบเจ็กต์จะกลายเป็น None

model_obj ว่างเปล่าเมื่อส่งคืนในโค้ดต่อไปนี้:

    model_obj = json.loads(model_serialized, object_hook=from_json)

try:
    session.add(model_obj)
    session.commit()
    config.logger.debug("added model_obj", model_obj=model_obj)
except IntegrityError as e:
    config.logger.debug("model_obj already exists", model_obj=model_obj, e=str(e))
    return createAndEncodeErrorElements(
        ErrorCodeDatabaseSQLAlchemyIntegrityError, None
    )
else:
    response = createAndEncodeSuccessElementsWithData({model_obj: model_obj})
    return response
finally:
    session.close()

model_obj ไม่ว่างเปล่าเมื่อส่งคืนในโค้ดต่อไปนี้: model_obj = json.loads(model_serialized, object_hook=from_json)

try:
    session.add(model_obj)
    config.logger.debug("added model_obj", model_obj=model_obj)
except IntegrityError as e:
    config.logger.debug("model_obj already exists", model_obj=model_obj, e=str(e))
    return createAndEncodeErrorElements(
        ErrorCodeDatabaseSQLAlchemyIntegrityError, None
    )
else:
    response = createAndEncodeSuccessElementsWithData({model_obj: model_obj})
    return response
finally:
    session.commit()
    session.close()

เหตุใด session.commit() จึงต้องอยู่ในส่วนคำสั่งสุดท้าย? พฤติกรรมพื้นฐานของ SQLAlchemy คืออะไร


person jon077    schedule 03.05.2020    source แหล่งที่มา
comment
โปรดระบุตัวอย่างที่ทำซ้ำได้น้อยที่สุด โดยมีอินพุตที่ชัดเจน และเอาต์พุตตามจริงและที่ต้องการ model_obj กลายเป็น None ไม่ใช่สิ่งที่ SQLAlchemy ควรจะเกี่ยวข้อง และฉันคิดว่าปัญหาของคุณซ่อนอยู่ใน createAndEncodeSuccessElementsWithData หากเป็นเช่นนั้น ในทางกลับกัน หากคุณหมายถึงคุณลักษณะของ model_obj กลายเป็น None ดูว่า @snakecharmerb ตอบอะไร   -  person Ilja Everilä    schedule 03.05.2020


คำตอบ (1)


SQLAlchemy หมดอายุ ออบเจ็กต์ทั้งหมดในเซสชันเมื่อเซสชัน มีความมุ่งมั่น. กล่าวคือ คุณลักษณะค่าคอลัมน์ทั้งหมดของอินสแตนซ์แบบจำลองจะถูกลบออกจาก __dict__

ซึ่งสามารถป้องกันได้โดยการส่ง expire_on_commit=False เมื่อสร้างเซสชัน โปรดทราบว่าข้อมูลในอินสแตนซ์ที่หมดอายุอาจเป็นข้อมูลเก่า

person snakecharmerb    schedule 03.05.2020
comment
FWIW ฉันจะเก็บ commit ไว้ในบล็อก try หรือ else และ rollback ไว้ในบล็อก except เพียง close-ing ในบล็อก finally - person snakecharmerb; 03.05.2020