2016-11-18 15 views
8

Ứng dụng của tôi SQLAlchemy (chạy trên đầu trang của MariaDB) bao gồm hai mô hình MyModelAMyModelB hợp tổ chức đó là một đứa trẻ kỷ lục của cựu:Lỗi trong SQLAlchemy Rollback sau khi ngoại lệ DB?

class MyModelA(db.Model): 
    a_id = db.Column(db.Integer, nullable=False, primary_key=True) 
    my_field1 = db.Column(db.String(1024), nullable=True) 

class MyModelB(db.Model): 
    b_id = db.Column(db.Integer, nullable=False, primary_key=True) 
    a_id = db.Column(db.Integer, db.ForeignKey(MyModelA.a_id), nullable=False) 
    my_field2 = db.Column(db.String(1024), nullable=True) 

Đây là những trường hợp của MyModelAMyModelB mà tôi tạo ra:

>>> my_a = MyModelA(my_field1="A1") 
>>> my_a.aid 
1 
>>> MyModelB(a_id=my_a.aid, my_field2="B1") 

tôi có đoạn mã sau đó xóa các thể hiện của MyModelA nơi a_id==1:

db.session.commit() 
try: 
    my_a = MyModelA.query.get(a_id=1) 
    assert my_a is not None 
    print "#1) Number of MyModelAs: %s\n" % MyModelA.query.count() 
    db.session.delete(my_a) 
    db.session.commit() 
except IntegrityError: 
    print "#2) Cannot delete instance of MyModelA because it has child record(s)!" 
    db.session.rollback() 
    print "#3) Number of MyModelAs: %s\n" % MyModelA.query.count() 

Khi tôi chạy cái nhìn mã này ở kết quả bất ngờ tôi nhận được:

#1) Number of MyModelAs: 1 
#2) Cannot delete instance of MyModelA because it has child record(s)! 
#3) Number of MyModelAs: 0 

Các xóa được cho là thất bại và DB ném một ngoại lệ mà gây ra một rollback. Tuy nhiên, ngay cả sau khi quay trở lại, số hàng trong bảng cho biết rằng hàng - được cho là không bị xóa - thực sự đã biến mất !!!

Tại sao điều này lại xảy ra? Làm thế nào tôi có thể sửa lỗi này? Nó có vẻ giống như một lỗi trong SQLAlchemy.

+0

bạn đã kiểm tra xem có tự động vô hiệu hóa không? –

+0

cùng một ý tưởng: bạn nói rằng bạn sử dụng MariaDB. Loại động cơ nào trong MariaDB? MyISAM không hỗ trợ các giao dịch, vì vậy nó luôn ở chế độ "tự động" –

+0

Các truy vấn được tạo ra bởi sqlalchemy là gì? 'SELECTs' có' FOR UPDATE' không? –

Trả lời

0

TL; DR Sự cố của bạn có thể liên quan đến việc thiếu tuyên bố quan hệ rõ ràng.

Ví dụ: here có một mẫu mối quan hệ của đối tượng. Ngoài việc sử dụng trường ForeignKey, lớp này sử dụng chỉ thị relationship một cách rõ ràng để xác định kết nối đó. Trong session API documentation, các văn bản sau đây xuất hiện:

tham chiếu đối tượng nên được xây dựng ở cấp đối tượng, chứ không phải ở cấp chính nước ngoài

Mà có thể ngụ ý cách SQLAlchemy để quản lý các mối quan hệ. Tôi không quen thuộc sâu sắc với các cơ chế cơ bản, nhưng có thể đây là những gì xảy ra. Phiên của bạn chỉ bao gồm đối tượng MyModelA. Vì bạn không sử dụng chỉ thị relationship() trong định nghĩa MyModelB, các đối tượng thuộc loại MyModelA không nhận thức được thực tế rằng một số đối tượng khác có thể giới thiệu chúng thông qua một ForeignKey. Do đó, khi phiên giao dịch sắp kết thúc, nó không nhận thức được rằng việc xóa đối tượng ảnh hưởng đến một số đối tượng khác MyModelB và cơ chế giao dịch của nó không tính đến điều đó. Tôi đề nghị thêm mối quan hệ một cách rõ ràng có thể ngăn chặn hành vi đó.

Các vấn đề liên quan