Russian Qt Forum

Qt => Базы данных => Тема начата: DpoHro от Июль 11, 2009, 00:25



Название: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: DpoHro от Июль 11, 2009, 00:25
Хочу выяснить почему возникает подобная ситуация впринципе.

У меня создается подключение с одним именем на все приложение.
Так получилось что сейчас я модифицирую код и случилось что часть работы с БД ведется не в потоке.
Происходит событие, которое запускает поток в котором выполняется несколько последовательных запросов и в это же время идут запросы в коде расположенным вне потока.
Сдается мне, что при такой одновременной работе с одним подключением к БД и кроется access violation.

Так ли это и как этого избежать?


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: ритт от Июль 11, 2009, 01:06
!rtfm: QSqlDatabase::cloneDatabase


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: DpoHro от Июль 11, 2009, 09:53
Так а можно наверное же делать так:
- создать подключение
- при необходимости клонировать его на один цикл операций и затем убивать клон?


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: ритт от Июль 11, 2009, 15:13
можно


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: DpoHro от Июль 11, 2009, 21:23
У меня за один раз выполняется довольно много ф-ций в каждой если делать клона, открывать выполнять запросы и потом убивать, корректно ли это?


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: lit-uriy от Июль 11, 2009, 22:41
Ты делай клона, для каждого потока, т.к. в одном потоке всё равно обращение будет по очереди.


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: DpoHro от Июль 11, 2009, 22:58
У меня работа идет в одном потоке в нескольких классах сразу, муторно переделывать все, вот думаю если написать так чтобы в каждой ф-ии этих классов получать клона и убивать его после отработки запросов. Но мне кажется что частое  подключение к БД в этом случае замедлит работу.


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: DpoHro от Июль 11, 2009, 23:02
Трудно просто будет обработать все точки где нужно закрыть подключение, а закрывать надо, так как я работаю с БД которая расположена на обычном хостинге, а там имеется ограничение на количество подключений это раз и маленький таймаут, что приводит к потере подключения если его не закрывать.


Название: Re: Ошибка обращения к памяти при работе с БД и потоками
Отправлено: break от Август 09, 2009, 15:25
Вообще проблем с передачей подключения не должно быть и с закрытием этих подключений - идея о содержании своего подключения в каждом потоке правильная. Тем более что передавать то ничего не надо так как сам класс QSqlDatabase так устроен что с ним можно работать так:

Код
C++ (Qt)
bool CSomeClass::some_DB_func()
{
// получаем экземпляр класса БД подключения - причем можно взять подключение по умолчанию
// можно создать копию подключения по умолчанию - через функцию clone()
// можно вообще взять именованное подключение - второй параметр означает открывать соединение если оно не открыто
 
QSqlDatabase db = QSqlDatabase::database( m_sConnectionName, false );
 
// можно проверить установлено ли подключение и установить если надо (т.к. второй параметр в QSqlDatabase::database указан false)
bool b = db.open();
qDebug() << m_sOpenDatabase << b;
b = b && db.transaction();
qDebug() << m_sStartTran << b;
 
// далее можно работать с этим экземпляром, создавать на его основе запросы и др.
QSqlQuery pQuery = new QSqlQuery( db );
 
// после можно подтвердить или отменить сделанные изменения и закрыть соединение
db.commit();
db.close();
 
// при выходе за пределы видимости класс QSqlDatabase будет корректно  уничтожен причем [b]без потери ресурсов и ворнинга[/b]
}
 

Вообще QSqlDatabase is a value class. что определяет особенности работы с ним: Changes made to a database connection via one instance of QSqlDatabase will affect other instances of QSqlDatabase that represent the same connection.
Все это выдержки из офф. документации в ассистент - этот класс очень удобен и его никуда не нужно передавать - достаточно создать экземпляр в своей функции и работать!