2010-02-25 49 views
6

Tôi muốn biết liệu mở giao dịch trong giao dịch khác có an toàn và được khuyến khích không?Giao dịch trong giao dịch

Tôi có một phương pháp:

def foo(): 
    session.begin 
    try: 
      stuffs 
    except Exception, e: 
     session.rollback() 
     raise e 
    session.commit() 

và một phương pháp mà các cuộc gọi đầu tiên, bên trong một giao dịch:

def bar(): 
    stuffs 
    try: 
     foo() #<<<< there it is :) 
     stuffs 
    except Exception, e: 
     session.rollback() 
     raise e 
    session.commit() 

nếu tôi nhận được và ngoại lệ về phương thức foo, tất cả các hoạt động sẽ được được khôi phục? và mọi thứ khác sẽ hoạt động tốt cảm ơn !!

+1

Giao dịch lồng nhau (ví dụ: AUTONOMOUS_TRANSACTION của Oracle) được coi là chống mẫu ngoài hai trường hợp: Kiểm tra (do đó, thử được kiểm tra ngay cả khi câu lệnh quay lại) và Ghi nhật ký lỗi (để nắm bắt vị trí/khi lỗi xảy ra). Tất cả các trường hợp khác nên sử dụng savepoints. Heck, phạm vi giao dịch không thuộc về việc bị xử lý trong bất kỳ chức năng hoặc thủ tục nào; nó phải là trách nhiệm cuối cùng của người gọi để cam kết hoặc quay trở lại. –

+0

Đó là sự chuyển đổi. – user

Trả lời

15

Có hai cách để lồng các giao dịch trong SQLAlchemy. Một là các giao dịch ảo, trong đó SQLAlchemy theo dõi số lượng lệnh bắt đầu mà bạn đã phát hành và phát hành các cam kết chỉ khi giao dịch ngoài cùng cam kết. Tuy nhiên, việc khôi phục được phát hành ngay lập tức. Bởi vì giao dịch là ảo - tức là cơ sở dữ liệu không biết gì về việc lồng nhau, bạn không thể làm bất cứ điều gì với phiên đó sau khi khôi phục cho đến khi bạn khôi phục tất cả các giao dịch bên ngoài. Để cho phép sử dụng các giao dịch ảo, hãy thêm đối số subtransactions=True vào cuộc gọi begin(). Tính năng này tồn tại để cho phép bạn sử dụng kiểm soát giao dịch bên trong các chức năng có thể gọi cho nhau mà không theo dõi nếu bạn đang ở trong một giao dịch hay không. Để có ý nghĩa, hãy định cấu hình phiên bằng autocommit=True và luôn phát hành session.begin(subtransactions=True) trong chức năng giao dịch.

Cách khác để lồng các giao dịch là sử dụng các giao dịch lồng nhau thực. Chúng được thực hiện bằng cách sử dụng savepoints. Nếu bạn quay trở lại một giao dịch lồng nhau, tất cả các thay đổi được thực hiện trong giao dịch đó được khôi phục, nhưng giao dịch bên ngoài vẫn có thể sử dụng được và mọi thay đổi được thực hiện bởi giao dịch bên ngoài vẫn ở đó. Để sử dụng vấn đề giao dịch lồng nhau session.begin(nested=True) hoặc chỉ session.begin_nested(). Giao dịch lồng nhau không được hỗ trợ cho tất cả các cơ sở dữ liệu. kiểm tra thư viện bộ cấu hình chức năng SQLAlchemy của sqlalchemy.test.requires.savepoints nói này về sự hỗ trợ:

emits_warning_on('mssql', 'Savepoint support in mssql is experimental and may lead to data loss.'), 
    no_support('access', 'not supported by database'), 
    no_support('sqlite', 'not supported by database'), 
    no_support('sybase', 'FIXME: guessing, needs confirmation'), 
    exclude('mysql', '<', (5, 0, 3), 'not supported by database') 

Về giao dịch lồng nhau PostgreSQL SQLAlchemy chỉ làm việc tốt.

0

Bạn không thể, PostgreSQL không hỗ trợ các giao thức con. Bạn có thể muốn sử dụng savepoints, nhưng thats cái gì khác.

+0

ok. Nhưng tôi thực thi mã trên và sqlalchemy cho phép tôi làm điều đó. điều gì xảy ra sau bức màn? – bluefoot

+0

Tôi không có kinh nghiệm với SQLAlchemy những gì bao giờ hết, không thể giúp bạn ở đó. Nhưng tôi biết PostgreSQL không thể làm subtransactions, Oracle là một trong số ít cơ sở dữ liệu có thể thực hiện thủ thuật này. Xem hướng dẫn http://www.sqlalchemy.org/docs/session.html#managing-transactions cách các giao dịch và điểm lưu trữ của sqlalchemy thực hiện như thế nào. Và thử nghiệm, kiểm tra, kiểm tra! Đừng tin tưởng ORM của bạn khi nó trông giống như nó cho phép bạn làm những việc cơ sở dữ liệu của bạn không thể làm được ... –

+0

Cập nhật liên kết: http://docs.sqlalchemy.org/en/rel_1_0/orm/session_transaction.html#managing -transactions – Kate

0

Trên giao dịch lồng nhau PostgreSQL hoạt động tốt.

Vâng, bạn sẽ không gặp lỗi (chỉ là cảnh báo), điều đó đúng. Nhưng bạn không thể cam kết giao dịch bên trong và khôi phục giao dịch bên ngoài, giao dịch bên ngoài cũng sẽ khôi phục giao dịch bên trong.

BEGIN;

INSERT INTO x (foo) VALUES ('John');

BEGIN; -- CẢNH BÁO!

INSERT INTO y (bar) VALUES ('Jane');

COMMIT; - cam kết giao dịch nội bộ

ROLLBACK; - sẽ rollback cả hai chèn, không chỉ là chèn đầu tiên, một trong bảng "x"

Theo hiểu biết của tôi, Oracle là một trong số ít tùy chọn này.

+3

Không giao dịch postgresql lồng nhau. SQLAlchemy giao dịch lồng nhau. Giao dịch bên trong dẫn đến một cặp SAVEPOINT và RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT. Điều này dẫn đến hành vi mà người ta mong đợi từ các giao dịch lồng nhau. Nó thực sự được thực hiện với SAVEPOINTs trên phần cuối của Oracle. Tôi đã làm rõ câu trả lời cho phù hợp. –