[PYTHON] Fallstricke bei SQL Alchemy

Einführung

SQLAlchemy ist ein OR-Mapper, der häufig beim Zugriff auf eine Datenbank mit Python verwendet wird. Verwenden von sqlalchemy für den Zugriff auf DB mit Python fasst andere Dinge als SQL zusammen. Dieses Mal habe ich die Dinge zusammengefasst, die ein Problem sein können, wenn Sie SQL Alchemy nicht verstehen.

Umgebung

Was Sie mit SQL und SQL Alchemy erhalten können, ist anders

Sie können SQL-Anweisungen zusätzlich zur Aktualisierung mit ORM direkt in SQLAlchemy verwenden. Bitte beachten Sie, dass die beabsichtigten Informationen nicht abgerufen werden können, wenn die Methode zum Aktualisieren aus der Datenbank und die Methode zum Erfassen unterschiedlich sind.

Konkretes Beispiel

Selbst wenn Sie innerhalb derselben Sitzung versuchen, den Inhalt durch die SQL-Anweisung zu ändern, bevor Sie sich mit ORM verpflichten, wird derjenige vor dem Update verwendet. Das Gegenteil ist auch der Fall.

Experiment

Holen Sie sich nach dem Update mit SQL-Anweisung oder ORM diese mit SQL-Anweisung und ORM und zeigen Sie den Inhalt an.

Experimentelle Quelle

Wenn Sie eine neue Sitzung einrichten, werden Sie die DB-Informationen abrufen, sodass sowohl die Aktualisierungsfunktion als auch die Anzeigefunktion dieselbe Sitzung haben. Da die Aktualisierungsvariable die Anzeigevariable nicht beeinflussen möchte, werden Aktualisierung und Anzeige als separate Funktionen erstellt. Informationen zum Erstellen einer Sitzung finden Sie unter Zurück.

main.py



def get_mapper_and_query(local_session):
    print('============== query get ===============')
    records = local_session.execute("select * from pets where id = 3;")
    for record in records:
        print(record)
    print('============== mapper get ===============')
    pet2 = local_session.query(Pets).filter(Pets.id==3).first()
    print(pet2)
 
def update_mapper_and_query():
    local_session = SESSION()
    print('*************************** default ***************************')
    get_mapper_and_query(local_session)
    print('*************************** default ***************************\n')

    print('*************************** mapper update ***************************')
    pet = local_session.query(Pets).filter(Pets.id==3).first()
    pet.age = 10
    get_mapper_and_query(local_session)
    print('*************************** mapper update ***************************')

    print('*************************** query update ***************************')
    local_session.execute("update pets set age=20 where id = 3;")
    get_mapper_and_query(local_session)
    print('*************************** query update ***************************\n')

Ergebnis

Ursprünglich war das Alter 5 Jahre, aber es wird nur dann auf 10 Jahre aktualisiert, wenn es von ORM nach der Aktualisierung von ORM erworben wurde. Darüber hinaus wird nach dem Aktualisieren der SQL-Anweisung das Alter auf 20 aktualisiert, wenn die SQL-Anweisung erfasst wird, und 10, wenn das ORM aktualisiert wird, bleibt unverändert, wie es ist, wenn das ORM erfasst wird. Auf diese Weise ist das, was Sie erhalten können, unterschiedlich, wenn jede Aktualisierungsmethode und Erfassungsmethode unterschiedlich ist.


*************************** default ***************************
============== query get ===============
(3, 'mink', 5, datetime.datetime(1990, 2, 12, 0, 0))
============== mapper get ===============
id:3, name:mink, age:5, birthday:1990-02-12 00:00:00
*************************** default ***************************

*************************** mapper update ***************************
============== query get ===============
(3, 'mink', 5, datetime.datetime(1990, 2, 12, 0, 0))
============== mapper get ===============
id:3, name:mink, age:10, birthday:1990-02-12 00:00:00
*************************** mapper update ***************************
*************************** query update ***************************
============== query get ===============
(3, 'mink', 20, datetime.datetime(1990, 2, 12, 0, 0))
============== mapper get ===============
id:3, name:mink, age:10, birthday:1990-02-12 00:00:00
*************************** query update ***************************

Die Anzahl der Verbindungen zur DB wird erhöht

SQLAlchemy verfügt über eine Verbindungspoolfunktion. Wenn Sie das Programm dauerhaft ausführen möchten, erhöht sich die Anzahl der Verbindungen stetig, es sei denn, Sie wissen, wann die Verbindungen erstellt werden.

Konkretes Beispiel

Als ich einen WEB-Dienst zum Abrufen von DB-Informationen mit flask erstellt habe, habe ich die Obergrenze der Anzahl der DB-Sitzungen erreicht und einen Fehler gemacht.

Experiment

Erstellen Sie einen Dienst, der mit flask Informationen aus der Datenbank abruft, und überprüfen Sie die Anzahl der Verbindungen auf der DB-Seite.

Experimentelle Quelle

Es ist eine Quelle, die eine Sitzung für die Datenbank erstellt und Informationen zurückgibt, wenn eine Anforderung empfangen wird. Dieses Mal wird der Anwendungsname py_app der DB-Sitzung zum leichteren Verständnis zugewiesen. Für eine DB-Verbindung Zugriff auf DB mit Python mithilfe von sqlalchemy für eine Flasche [So geben Sie den http-Status mit einer Flasche zurück](https: / Siehe /qiita.com/mink0212/items/52e0ebd66bd94e1303c1).

main.py



from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from flask import Flask, jsonify
from Pets import Pets

DATABASE = 'postgresql'
USER = 'postgres'
PASSWORD = 'postgres'
HOST = 'localhost'
PORT = '5431'
DB_NAME = 'animal_db'


CONNECT_STR = '{}://{}:{}@{}:{}/{}'.format(
    DATABASE,
    USER,
    PASSWORD,
    HOST,
    PORT,
    DB_NAME
)

app = Flask(__name__)


@app.route('/hello/<name>')
def hello(name):
    engine = create_engine(CONNECT_STR, connect_args={"application_name":"py_app"})
    session = sessionmaker(engine)()
    pets = session.query(Pets).filter(Pets.name==name).all()
    return jsonify(pets)

if __name__ == "__main__":
    app.run()

Ergebnis

Anzahl der Sitzungen beim Start


postgres=# select count(*) from pg_stat_activity where application_name = 'py_app';
 count
-------
     0
(1 row)

Anzahl der Sitzungen nach der ersten Anfrage


postgres=# select count(*) from pg_stat_activity where application_name = 'py_app';
 count
-------
     1
(1 row)

Anzahl der Sitzungen nach der zweiten Anforderung


postgres=# select count(*) from pg_stat_activity where application_name = 'py_app';
 count 
-------
     2
(1 row)

Anzahl der Sitzungen nach der 30. Anfrage


postgres=# select count(*) from pg_stat_activity where application_name = 'py_app';
 count
-------
    30
(1 row)

Wie Sie sehen, wird jedes Mal, wenn Sie eine Anfrage stellen, eine Sitzung eingerichtet. Um dies zu verhindern, müssen Sie die Sitzung verschieben oder schließen und die Engine vor der Antwort entsorgen.

abschließend

Der Unterschied im diesmal erhaltenen Wert kann im Test festgestellt werden. Wenn die Sitzung jedoch nicht gut ist, wird sie möglicherweise nicht gefunden und ist sehr gefährlich. Einige Leute verwenden ORM, ohne es vollständig zu verstehen, weil es bequem zu verwenden ist, aber es ist notwendig, es vollständig zu verstehen, weil es von solchen Fallstricken abhängig sein kann.

Recommended Posts

Fallstricke bei SQL Alchemy
sqlalchemy
sqlalchemy Tutorial
SQLAlchemy note
SQLAlchemy BaseModel
[SQL Alchemy] Daten lesen