1 Востаннє редагувалося Betterthanyou (07.03.2023 23:17:23)

Тема: SQLITE Connection з SQLITE_OPEN_FULLMUTEX

Є багатопоточна python програма (скрипт). Яка із різних потоків звертається до бази даних

Питання: як зробити безпечне багатопотокове звернення до бази даних ?

Знайшов інформацію про SQLITE_OPEN_FULLMUTEX

SQLITE_OPEN_FULLMUTEX

The new database connection will use the "serialized" threading mode. This means the multiple threads can safely attempt to use the same database connection at the same time. (Mutexes will block any actual concurrency, but in this mode there is no harm in trying.)

Але не можу знайти жодного приклада з python

class Database:
    __instance = None

    @staticmethod
    def get_instance():
        """Static method to get the singleton instance of the class"""
        if Database.__instance is None:
            Database()
        return Database.__instance

    def __init__(self):
        dbpath = 'temp\db.sqlite'

        """Private constructor to create the singleton instance of the class"""
        if Database.__instance is not None:
            raise Exception("Singleton instance already exists. Use get_instance() to get the instance.")
        else:
            self.connection = sqlite3.connect(dbpath, check_same_thread=False)
            Database.__instance = self

        # Create the ChannelName table if it doesn't exist
        self.connection.execute('''
            CREATE TABLE IF NOT EXISTS ChannelName (
                id INTEGER PRIMARY KEY,
                name TEXT NOT NULL UNIQUE
            )
        ''')

        # Create the Settings table if it doesn't exist
        self.connection.execute('''
            CREATE TABLE IF NOT EXISTS Settings (
                id INTEGER PRIMARY KEY,
                image_path TEXT NOT NULL,
                font_path TEXT NOT NULL,
                highlight_color TEXT NOT NULL,
                text_color TEXT NOT NULL,
                channel_id INTEGER UNIQUE,
                FOREIGN KEY (channel_id) REFERENCES ChannelName(id)
            )
        ''')

        # Commit the changes
        self.connection.commit()

    def close(self):
        # Close the connection
        self.connection.close()

    def LoadData(self): 
        # Retrieve data from database
        data = self.connection.execute('''
            SELECT cn.id, cn.name, s.image_path, s.font_path, s.highlight_color, s.text_color
            FROM ChannelName cn
            JOIN Settings s
            ON cn.id = s.channel_id
        ''').fetchall()

        return data

Це що, SQLITE_OPEN_FULLMUTEX не існує для python ?

чи потрібно лок або мютекс використовувати?
import threading

class Database:
    __instance = None

    @staticmethod
    def get_instance():
        """Static method to get the singleton instance of the class"""
        if Database.__instance is None:
            Database()
        return Database.__instance

    def __init__(self):
        dbpath = 'temp\db.sqlite'

        """Private constructor to create the singleton instance of the class"""
        if Database.__instance is not None:
            raise Exception("Singleton instance already exists. Use get_instance() to get the instance.")
        else:
            self.connection = sqlite3.connect(dbpath, check_same_thread=False)
            Database.__instance = self

        # Create a lock object to ensure thread safety
        self.lock = threading.Lock()

        # Create the ChannelName table if it doesn't exist
        with self.lock:
            self.connection.execute('''
                CREATE TABLE IF NOT EXISTS ChannelName (
                    id INTEGER PRIMARY KEY,
                    name TEXT NOT NULL UNIQUE
                )
            ''')

        # Create the Settings table if it doesn't exist
        with self.lock:
            self.connection.execute('''
                CREATE TABLE IF NOT EXISTS Settings (
                    id INTEGER PRIMARY KEY,
                    image_path TEXT NOT NULL,
                    font_path TEXT NOT NULL,
                    highlight_color TEXT NOT NULL,
                    text_color TEXT NOT NULL,
                    channel_id INTEGER UNIQUE,
                    FOREIGN KEY (channel_id) REFERENCES ChannelName(id)
                )
            ''')

        # Commit the changes
        with self.lock:
            self.connection.commit()

    def close(self):
        # Close the connection
        with self.lock:
            self.connection.close()

    def LoadData(self): 
        # Retrieve data from database
        with self.lock:
            data = self.connection.execute('''
                SELECT cn.id, cn.name, s.image_path, s.font_path, s.highlight_color, s.text_color
                FROM ChannelName cn
                JOIN Settings s
                ON cn.id = s.channel_id
            ''').fetchall()

        return data

Якось так ?

Додаткова важлива інформація: Як ви бачите з коду я використовую Singleton (також в мене був cursor, який я видалив, тому що не впевнений чи він потрібний)

cursor = self.connection.cursor()

Чи можна використовувати Singleton в багато поточній програмі ? База даних файлова, так що зазвичай немає сенсу закривати з'єднання під час всього часу роботи програми, але не знаю чи це відноситься для багатопотокових програм

2

Re: SQLITE Connection з SQLITE_OPEN_FULLMUTEX

Є sqlite3.threadsafety=3.

Подякували: Betterthanyou, leofun012

3 Востаннє редагувалося Betterthanyou (08.03.2023 00:50:52)

Re: SQLITE Connection з SQLITE_OPEN_FULLMUTEX

Я думаю що threadsafety трішки не те

В С можна відкрити sqlite3_open_v2 з SQLITE_OPEN_FULLMUTEX (код не перевіряв)

#include <sqlite3.h>

int main() {
    sqlite3 *db;
    int result;

    // open the database connection with SQLITE_OPEN_FULLMUTEX flag
    result = sqlite3_open_v2("example.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);

    if (result != SQLITE_OK) {
        fprintf(stderr, "Error opening database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }

    // use the database connection...

    // close the database connection
    sqlite3_close(db);
    return 0;
}

А як це зробити з threadsafety для python ?

4

Re: SQLITE Connection з SQLITE_OPEN_FULLMUTEX

Я думаю що threadsafety трішки не те

я думаю, що вам треба трохи менше думати і трохи більше читати документацію. Це САМЕ ТОЙ параметр.