Поток BLOB в MySQL с помощью SQLAlchemy - PullRequest
0 голосов
/ 07 марта 2019

Иногда возникают проблемы с записью больших двоичных объектов в базу данных MySQL. Для хранения блоба в базе данных он должен быть загружен в память, иногда мой процесс убивает OOM killer. Поэтому я думаю, что потоковая передача могла бы решить мои проблемы, но я не нашел никакой информации о возможности потоковой передачи BLOB-данных в MySQL с помощью SQLAlchemy.

1 Ответ

0 голосов
/ 30 марта 2019

Я принимаю комментарий Раймонда, но мне все еще нужно решение.И я нашел это.Если вы хотите передавать данные в BLOB, вы можете использовать этот странный хак:

import sqlalchemy as sa
from sqlalchemy import func
from sqlalchemy.dialects.mysql import LONGBLOB
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session

Base = declarative_base()


def read_data_from_disk(compressed_report_file: str, stream_chunk: int):
    with open(compressed_report_file, 'rb') as compressed_report:
        compressed_report_data = compressed_report.read(stream_chunk)
        while compressed_report_data:
            yield compressed_report_data
            del compressed_report_data
            compressed_report_data = compressed_report.read(stream_chunk)


class TestData(Base):
    __tablename__ = 'test_data'
    id = sa.Column(sa.BigInteger, nullable=False, autoincrement=True, primary_key=True)
    data = sa.Column(LONGBLOB, nullable=False)

    @classmethod
    def save_data(cls, session: Session, file_name: str, stream_chunk: int = 1024 ** 2):
        saved_data = cls(data=b'')
        session.add(saved_data)
        try:
            session.flush()
            saved_data_id = saved_data.id
            for file_data in read_data_from_disk(file_name, stream_chunk):
                session.query(cls).filter(cls.id == saved_data_id).update({
                    cls.data: func.concat(cls.data, file_data)
                }, synchronize_session=False)

        except Exception:
            session.rollback()
            raise

        return saved_data_id


db = sa.create_engine('mysql://login:password@host:3306/database?charset=utf8')
session = Session(bind=db)

TestData.save_data(session=session, file_name='FatFile')
session.commit()

Я положил в файл базы данных:

AT-MBP-7:Python atolkachev$ ls -l FatFile
-rw-r--r--@ 1 atolkachev  staff  35229330 Mar  8 01:30 FatFile

Результат в базе данных:

mysql> select id, OCTET_LENGTH(data) from test_data;
+----+--------------------+
| id | OCTET_LENGTH(data) |
+----+--------------------+
|  1 |           35229330 |
+----+--------------------+
1 row in set (0.00 sec)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...