Уровни изоляции в колбе SQLAlchemy [дубликат]

Способ думать об этом - «думать как компилятор».

Представьте, что вы пишете компилятор. И вы видите такой код.

// file: A.h
class A {
  B _b;
};

// file: B.h
class B {
  A _a;
};

// file main.cc
#include "A.h"
#include "B.h"
int main(...) {
  A a;
}

Когда вы компилируете файл .cc (помните, что .cc, а не .h - это единица компиляции), вам нужно выделить пространство для объекта A. Итак, хорошо, сколько пространства тогда? Достаточно хранить B! Каков размер B? Достаточно хранить A!

Очевидно, что круговая ссылка, которую вы должны сломать.

Вы можете ее разбить, разрешив компилятору зарезервировать столько места, сколько он знает о указателях и ссылках на передний план, для например, всегда будет 32 или 64 бита (в зависимости от архитектуры), и поэтому, если вы замените (или один) указателем или ссылкой, все будет замечательно. Скажем, мы заменим в A:

// file: A.h
class A {
  // both these are fine, so are various const versions of the same.
  B& _b_ref;
  B* _b_ptr;
};

Теперь все лучше. В некотором роде. main() все еще говорит:

// file: main.cc
#include "A.h"  // <-- Houston, we have a problem

#include, для всех экстентов и целей (если вы выберете препроцессор) просто копирует файл в .cc. Так что, .cc выглядит так:

// file: partially_pre_processed_main.cc
class A {
  B& _b_ref;
  B* _b_ptr;
};
#include "B.h"
int main (...) {
  A a;
}

Вы можете понять, почему компилятор не может с этим справиться - он понятия не имеет, что B - он даже не видел символ раньше .

Итак, давайте расскажем компилятору о B. Это известно как декларация вперед и обсуждается далее в этом ответе .

// main.cc
class B;
#include "A.h"
#include "B.h"
int main (...) {
  A a;
}

Это работает . Это не отлично . Но на этом этапе у вас должно быть понимание проблемы с круговой ссылкой и что мы сделали, чтобы «исправить» ее, хотя исправление плохо.

Причина, по которой это исправление плохо, заключается в следующем: f17] должны объявить B, прежде чем они смогут его использовать, и получите ужасную ошибку #include. Итак, давайте переместим декларацию в себя.

// file: A.h
class B;
class A {
  B* _b; // or any of the other variants.
};

И в Bh на данный момент вы можете просто #include "A.h" прямо.

// file: B.h
#include "A.h"
class B {
  // note that this is cool because the compiler knows by this time
  // how much space A will need.
  A _a; 
}

HTH.

5
задан hllau 12 September 2012 в 09:44
поделиться

1 ответ

Возможно, вам захочется посмотреть на этот вопрос SQL-загрузчик связей Alchemy оставляет блокировку на таблице?

Что вам нужно сделать, это подкласс flask.ext.sqlalchemy.SQLAlchemy и переопределить метод apply_driver_hacks для прохождения через дополнительный аргумент ключевого слова isolation_level='READ <some level>' :

from flask.ext.sqlalchemy import SQLAlchemy

class UnLockedAlchemy(SQLAlchemy):
    def apply_driver_hacks(self, app, info, options):
        if not "isolation_level" in options:
            options["isolation_level"] = "READ COMMITTED"  # For example
        return super(UnLockedAlchemy, self).apply_driver_hacks(app, info, options)
7
ответ дан Community 25 August 2018 в 10:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: