マルチスレッドアクセスデータベース問題
7026 ワード
最近マルチスレッドのリモートアップグレードソフトを作って、完成したら対応するテストプログラムを使ってテストします。スレッドが複数あると必ず崩壊します。すべてのデータベース処理を全部削除したら、同時に何百スレッドも実行できます。原因は自分でシングルモードを採用して、各スレッドの中でTcpServerに信号を送ります。serverでは、単一スレッドでSqlite Toolの単一の例のオペレーティングデータベースを呼び出します。これはより安全で効率的であるべきだと思いましたが、今はマルチスレッドでスタティック関数を加えるべきです。
2018/3/23更新:
1.ワンケースモードは使用しないでください。マルチスレッドアクセスの対象はピットです。Javaの下の接続プールの管理対象は一例ですが、接続プールのオブジェクトは複数です。静的関数で大丈夫です。
QtデータベースはQSql Database:addDatabase()によって生成されたQSql Databaseはその作成スレッドでしか使用できません。マルチスレッドで接続を共有したり、他のスレッドでqueryを作成したりするのはサポートされていません。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2)データベーススレッド池を実現し、Nつの異なるconnectionation Nameを作成するQSQSql Database。すべてのqueryコマンドをこのスレッド池に置いて処理する。
ここでネットの大牛に感謝します。
参照先:
http://blog.csdn.net/goldenhawking/article/details/10811409
http://blog.chinaunix.net/uid-20680966-id-4779621.html
他の二つのパッケージ
http://blog.csdn.net/wsj18808050/article/details/44891715
http://blog.csdn.net/lwwl12/article/details/76124210
2018/3/23更新:
1.ワンケースモードは使用しないでください。マルチスレッドアクセスの対象はピットです。Javaの下の接続プールの管理対象は一例ですが、接続プールのオブジェクトは複数です。静的関数で大丈夫です。
#include "dbtool.h"
#include
#include
#include
#include
#include
QMutex DBTool::mutex4Thread;
DBTool::DBTool()
{
qDebug()<
使う時はロックをかけます。二つのQSql Databaseの対象は部分的にして、removeしなければなりません。void TcpThread::db_progress(double progress)
{
QMutexLocker locker(&DBTool::mutex4Thread);
QString progressStr=QString::number(progress*100,'f',2)+"%";
{
QSqlDatabase db=DBTool::getConnection();
QSqlQuery query(db);
query.prepare("UPDATE table_all set progress = :progress WHERE id LIKE :id");
query.bindValue(":progress",progressStr);
query.bindValue(":id",_id);
if(!query.exec())
{
qDebug()<
2.データベース画面を更新し、Query操作をサブスレッド内に入れて、メインスレッドで時間をつぶしないようにしてください。#include "sql4ui.h"
#include
#include
#include "tool/dbtool.h"
#include
#include
#include
#include "global.h"
#include
Sql4ui::Sql4ui(QObject *obj, int request, int page_num, QString filter_sql, QString query_filter) : QRunnable()
{
_obj=obj;
_request=request;
_page_num=page_num;
_filter_sql=filter_sql;
_query_filter=query_filter;
}
Sql4ui::~Sql4ui()
{
}
void Sql4ui::run()
{
if(_request==0) //
{
refresh_table();
}
else if(_request==1) //
{
query_count();
}
}
void Sql4ui::refresh_table()
{
{
QSqlDatabase db=DBTool::getConnection();
int count=0;
//QString cells[ROW_OF_TABLE][COLUMN_OF_TABLE];
// [] resize
QVector> cells(ROW_OF_TABLE);
for(int i=0;i vec(COLUMN_OF_TABLE);
cells[i]=vec;
}
{
QMutexLocker locker(&DBTool::mutex4Thread);
// where_sql count
QSqlQuery query1("SELECT count(*) FROM table_all"+_filter_sql,db);
if(query1.next())
{
count=query1.value(0).toInt();
}
QSqlQuery query(db);
int start=(_page_num-1)*ROW_OF_TABLE;
if(_filter_sql!="")
{
query.prepare("SELECT * FROM table_all "+_filter_sql+" ORDER BY id");
if(query.exec())
{
int rowIndex=0;
if(query.seek(start))
{
bool is_next_ok=true;
while(is_next_ok&&rowIndex :start AND id <= :end");
query.bindValue(":start",start);
query.bindValue(":end",end);
if(query.exec())
{
int rowIndex=0;
while(query.next())
{
cells[rowIndex][0]=query.value("id").toString();
cells[rowIndex][1]=query.value("SA").toString();
cells[rowIndex][2]=query.value("status").toString();
cells[rowIndex][3]=query.value("progress").toString();
cells[rowIndex][4]=query.value("error").toString();
cells[rowIndex][5]=query.value("datetime").toString();
rowIndex++;
}
}
}
}
QMetaObject::invokeMethod(_obj,"invokeTable",Qt::QueuedConnection,Q_ARG(int,count),Q_ARG(QVector>,cells));
}
DBTool::removeConnection();
}
void Sql4ui::query_count()
{
{
QSqlDatabase db=DBTool::getConnection();
int count=0;
{
QMutexLocker locker(&DBTool::mutex4Thread);
QSqlQuery query(db);
query.prepare("SELECT count(*) FROM table_all "+_query_filter);
if(query.exec())
{
if(query.next())
{
count=query.value(0).toInt();
}
}
}
QMetaObject::invokeMethod(_obj,"invokeQueryCount",Qt::QueuedConnection,Q_ARG(int,count));
}
DBTool::removeConnection();
}
参照QtデータベースはQSql Database:addDatabase()によって生成されたQSql Databaseはその作成スレッドでしか使用できません。マルチスレッドで接続を共有したり、他のスレッドでqueryを作成したりするのはサポートされていません。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
:
bool
openDatabase()
{
QSqlDatabase db;
QString connectionName =
"sqlite"
;
db = QSqlDatabase::addDatabase(
"QSQLITE"
, connectionName);
db.setDatabaseName(
"/jyxtec.db"
);
if
(db.open())
return
true
;
else
return
false
;
}
void
testQuery()
{
QSqlQuery query(QSqlDatabase::database(
"sqlite"
));
query.exec(
"SELECT * from t_test"
);
}
ここのtestQuery()はマルチスレッドの呼び出しをサポートしていません。OpenDatabase()を起動するスレッドでのみ使用できます。そうでないと、エラーが発生しやすいです。解決方法は2つあります。1)testQueryを呼び出すスレッドごとに、異なるconnection Nameを作成するQSql DatabaseなどのスレッドAQSql Databaseを作成します。QSqlQuery query(QSql Database::database(“A”);スレッドBQSql Database:addDatabase(「QSQLITE」「B」);QSqlQuery query(QSql Database::database(「B」);2)データベーススレッド池を実現し、Nつの異なるconnectionation Nameを作成するQSQSql Database。すべてのqueryコマンドをこのスレッド池に置いて処理する。
ここでネットの大牛に感謝します。
参照先:
http://blog.csdn.net/goldenhawking/article/details/10811409
http://blog.chinaunix.net/uid-20680966-id-4779621.html
他の二つのパッケージ
http://blog.csdn.net/wsj18808050/article/details/44891715
http://blog.csdn.net/lwwl12/article/details/76124210