#include "sqliteread.h" #include SQLiteReadWrite::SQLiteReadWrite(QObject *parent) : QObject(parent) { m_connectionName = QString("SQLiteConnection_%1").arg(reinterpret_cast(this)); idValue = 0; m_stopRequested = false; } SQLiteReadWrite::~SQLiteReadWrite() { if (!m_isClosed) { closeDatabase(); } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } bool SQLiteReadWrite::openDatabase(const QString &dbPath) { QMutexLocker locker(&m_mutex); if (!m_isClosed) { closeDatabase(); } // 确定数据库路径 QString path = dbPath; if (path.isEmpty()) { QString appDir = QCoreApplication::applicationDirPath(); path = QDir(appDir).filePath("test_readwrite.db"); } m_dbPath = path; // 打开数据库 m_database = QSqlDatabase::addDatabase("QSQLITE", m_connectionName); m_database.setDatabaseName(m_dbPath); if (!m_database.open()) { log(QString("打开数据库失败: %1").arg(m_database.lastError().text())); return false; } // 启用外键和WAL模式(提高并发性能) QSqlQuery query(m_database); // 开启外键约束 if (!query.exec("PRAGMA foreign_keys = ON;")) { log(QString("启用外键失败: %1").arg(query.lastError().text())); } // 开启WAL模式(写时复制,提高读写并发性能) if (!query.exec("PRAGMA journal_mode = WAL;")) { log(QString("启用WAL模式失败: %1").arg(query.lastError().text())); } // // 设置同步模式(在安全性和性能之间权衡) // if (!query.exec("PRAGMA synchronous = NORMAL;")) { // log(QString("设置同步模式失败: %1").arg(query.lastError().text())); // } // 设置缓存大小 if (!query.exec("PRAGMA cache_size = 10000;")) { log(QString("设置缓存大小失败: %1").arg(query.lastError().text())); } m_isClosed = false; log(QString("数据库打开成功: %1").arg(m_dbPath)); return true; } void SQLiteReadWrite::closeDatabase() { QMutexLocker locker(&m_mutex); if (m_isClosed) { return; } m_isClosed = true; if (m_database.isOpen()) { m_database.close(); log("数据库已关闭"); } if (QSqlDatabase::contains(m_connectionName)) { QSqlDatabase::removeDatabase(m_connectionName); } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } void SQLiteReadWrite::startReadWriteOperation() { if (!m_database.isOpen()) { emit operationCompleted(false, "数据库未打开"); return; } m_stopRequested = false; //在单独的线程中执行,避免阻塞UI QtConcurrent::run(this, &SQLiteReadWrite::processReadWrite); } void SQLiteReadWrite::stopOperation() { m_stopRequested = true; log("stop requese send"); } void SQLiteReadWrite::processReadWrite() { m_timer.start(); log("开始边读边写操作..."); try { processWithMultipleConnections(); if (!m_stopRequested) { qint64 elapsed = m_timer.elapsed(); QString message = QString("操作完成,总耗时: %1 毫秒").arg(elapsed); log(message); emit operationCompleted(true, message); } else { emit operationCompleted(false, "quxiao"); } } catch (const std::exception &e) { log(QString("发生异常: %1").arg(e.what())); emit operationCompleted(false, QString("异常: %1").arg(e.what())); } } void SQLiteReadWrite::processWithMultipleConnections() { const QString readConnName = m_connectionName + "_read"; int totalRecords = 0; int processedRecords = 0; bool readSuccess = false; { QSqlDatabase readDb = QSqlDatabase::addDatabase("QSQLITE", readConnName); readDb.setDatabaseName(m_dbPath); if (!readDb.open()) { QString logMsg = QString("打开读取连接失败: %1").arg(readDb.lastError().text()); log(logMsg.toUtf8().constData()); emit operationCompleted(false, "无法打开数据库连接"); return; } { QSqlQuery optimizeQuery(readDb); optimizeQuery.exec("PRAGMA journal_mode = WAL;"); optimizeQuery.exec("PRAGMA synchronous = OFF;"); optimizeQuery.exec("PRAGMA cache_size = -200000;"); // 200MB缓存 optimizeQuery.exec("PRAGMA temp_store = MEMORY;"); optimizeQuery.exec("PRAGMA mmap_size = 2147483648;"); // 2GB内存映射 optimizeQuery.exec("PRAGMA query_only = ON;"); optimizeQuery.finish(); } { QSqlQuery countQuery(readDb); if (countQuery.exec("SELECT COUNT(*) FROM lmdatainfov2")) { countQuery.next(); totalRecords = countQuery.value(0).toInt(); } countQuery.finish(); } if (totalRecords == 0) { log("数据库中无记录"); readDb.close(); emit operationCompleted(false, "数据库中无有效数据"); return; } QString totalMsg = QString("GVF数据库总记录数: %1 条").arg(totalRecords); log(totalMsg.toUtf8().constData()); const int pageSize = 200; int lastId = 0; m_DataBaseList.clear(); m_DataBaseList.reserve(totalRecords); while (!m_stopRequested) { QSqlQuery readQuery(readDb); readQuery.setForwardOnly(true); readQuery.prepare("SELECT id, data FROM lmdatainfov2 WHERE id > :lastId ORDER BY id LIMIT :limit"); readQuery.bindValue(":lastId", lastId); readQuery.bindValue(":limit", pageSize); if (!readQuery.exec()) { QString errMsg = QString("数据读取失败: %1").arg(readQuery.lastError().text()); log(errMsg.toUtf8().constData()); readQuery.finish(); break; } int pageRecords = 0; while (readQuery.next() && !m_stopRequested) { DataBaseStruct data; data.id = readQuery.value(0).toInt(); data.data = readQuery.value(1).toByteArray(); m_DataBaseList.append(data); lastId = data.id; pageRecords++; } readQuery.finish(); readQuery.clear(); if (pageRecords == 0) { break; } processedRecords += pageRecords; int remainingRecords = totalRecords - processedRecords; int progress = (processedRecords * 100) / totalRecords; emit progressUpdated(progress, processedRecords, totalRecords); } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); readDb.close(); readSuccess = true; } QThread::msleep(50); if (QSqlDatabase::contains(readConnName)) { QSqlDatabase::removeDatabase(readConnName); } QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } QSqlDatabase SQLiteReadWrite::createConnection() { QString connName = QString("TempConnection_%1_%2") .arg(m_connectionName) .arg(QDateTime::currentMSecsSinceEpoch()); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connName); db.setDatabaseName(m_dbPath); if (!db.open()) { log(QString("创建临时连接失败: %1").arg(db.lastError().text())); } return db; } void SQLiteReadWrite::log(const QString &message) { QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); QString logMsg = QString("[%1] %2").arg(timestamp).arg(message); emit logMessage(logMsg); } QVector SQLiteReadWrite::DataBaseList() const { QMutexLocker locker(&m_mutex); return m_DataBaseList; } QString SQLiteReadWrite::getMeasureStartTime() { QMutexLocker locker(&m_mutex); if (m_isClosed || !m_database.isOpen()) { log("Database not open, cannot read statistic starttime"); return ""; } QSqlQuery query(m_database); // lmstatisticinfov2 存储本次测量标准起止时间 if (!query.exec("SELECT starttime FROM lmstatisticinfov2 LIMIT 1;")) { log(QString("Query lmstatisticinfov2 failed: %1").arg(query.lastError().text())); return ""; } if (query.next()) { return query.value("starttime").toString(); } log("lmstatisticinfov2 table has no starttime record"); return ""; } void SQLiteReadWrite::setIdValue(int value) { idValue = value; }