Строки, вставленные в таблицу mysql после запуска приложения, не выбираются приложением

0

У меня есть usecase в whch Мне нужно читать rows имеющие status = 0 из mysql.

Схема таблицы:

CREATE TABLE IF NOT EXISTS in_out_analytics(
                id INT AUTO_INCREMENT PRIMARY KEY, 
                file_name VARCHAR(255), 
                start_time BIGINT, 
                end_time BIGINT,
                duration INT,
                in_count INT,
                out_count INT,
                status INT
            )

Я использую этот ниже код для чтения данных из mysql.

persistance.py

import mysql
import mysql.connector
import conf

class DatabaseManager(object):
    # global vars to storing db connection details
    connection = None 

    def __init__(self): 
        self.ip = conf.db_ip
        self.user_name = conf.db_user
        self.password = conf.db_password
        self.db_name = conf.db_name

        # Initialize database only one time in application
        if not DatabaseManager.connection:
            self.connect()
        self.cursor = DatabaseManager.connection.cursor() 
        self.create_schema()

    def connect(self): 
        try: 
            DatabaseManager.connection = mysql.connector.connect(
                    host= self.ip, 
                    database = self.db_name,
                    user = self.user_name, 
                    password = self.password
            )
            print(f"Successfully connected to { self.ip } ") 
        except mysql.connector.Error as e: 
            print(str(e)) 

    def create_schema(self):
        # Create database
        # sql = f"CREATE DATABASE { self.db_name} IF NOT EXIST"
        # self.cursor.execute(sql)

        # Create table
        sql = """
            CREATE TABLE IF NOT EXISTS in_out_analytics(
                id INT AUTO_INCREMENT PRIMARY KEY, 
                file_name VARCHAR(255), 
                start_time BIGINT, 
                end_time BIGINT,
                duration INT,
                in_count INT,
                out_count INT,
                status INT
            )"""
        self.cursor.execute(sql)

    def read_unprocessed_rows(self):
        sql = "SELECT id, start_time, end_time FROM in_out_analytics WHERE status=0;"
        self.cursor.execute(sql) 
        result_set = self.cursor.fetchall()
        rows = []
        for row in result_set:
            id = row[0]
            start_time = row[1]
            end_time = row[2]
            details = {
                'id' : id,
                'start_time' : start_time,
                'end_time' : end_time
            }
            rows.append(details)
        return rows

test.py

import time
from persistance import DatabaseManager


if __name__ == "__main__":

    # Rows which are inserted after application is started do not get processed if  
    # 'DatabaseManager' is defined here
    # dm = DatabaseManager()

    while True:
        # Rows which are inserted after application is started do get processed if  
        # 'DatabaseManager' is defined here
        dm = DatabaseManager()

        unprocessed_rows = dm.read_unprocessed_rows()
        print(f"unprocessed_rows: { unprocessed_rows }")
        time.sleep(2)

Проблема:

Проблема заключается в том, что когда я определяю объект базы данных dm = DatabaseManager() над циклом while, любая новая строка, вставленная после запуска приложения, не обрабатывается, и если я определяю dm = DatabaseManager() внутри цикла while, строки, которые вставлены даже после запуска приложения, обрабатываются.

В чем проблема с вышеуказанным кодом?

В идеале мы должны сделать только один объект DatabaseManager как этот класс создает соединение с MySQL. Следовательно, создание соединения с любой базой данных должно быть идеальным.

Теги:
database
python-3.x
mysql-python

1 ответ

0

Сделав здесь предположение, поскольку я не могу проверить его сам.

tl; dr: Добавить DatabaseManager.connection.commit() в ваш read_unprocessed_rows

Когда вы выполняете оператор SELECT, транзакция создается неявно, используя уровень изоляции по умолчанию REPEATABLE READ. Это создает моментальный снимок базы данных в этот момент времени, и все последовательные чтения в этой транзакции будут считываться из моментального снимка, установленного во время первого чтения. Влияние различных уровней изоляции описаны здесь. Чтобы обновить моментальный снимок в REPEATABLE READ, вы можете перенести свою текущую транзакцию перед выполнением следующего оператора.

Поэтому, когда вы создаете экземпляр DatabaseManager внутри цикла, каждый SELECT запускает новую транзакцию в новом соединении, поэтому каждый раз имеет новый снимок. При создании экземпляра вашего Databasemanager вне цикла транзакция, созданная первым SELECT, сохраняет тот же снимок для всех последовательных SELECT и обновлений извне, транзакция остается невидимой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню