Сбой отката транзакций Qt на MySQL
Я пытаюсь использовать транзакции внутри соединения Qt, но не могу понять, как они работают правильно. Моя база данных - это экземпляр MySQL, а в таблицах используется механизм InnoDB, поэтому транзакции поддерживаются.
Я написал небольшой тест, в котором внутри транзакции я удаляю запись в таблице и в итоге создаю таблицу, которая уже существует. Когда сценарий создания терпит неудачу, я пытаюсь обработать это, откатываясь
Я ожидаю, что при откате запись не будет удалена. Однако, что я получил, так это то, что как только вызывается функция отката, запись удаляется.
#include <QApplication>
#include <QtSql>
#include <QtDebug>
int main( int argc, char **argv )
{
QApplication app( argc, argv );
QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
db.setHostName( QString("XXXXX")) ;
db.setDatabaseName( "db_test" );
db.setUserName( "X" );
db.setPassword( "X" );
QSqlDatabase::database().transaction();
QSqlQuery q;
if( !db.open() )
{
qDebug() << db.lastError();
qFatal( "Failed to connect." );
}
qDebug( "Connected!" );
q.prepare("DELETE FROM vendita WHERE matricola = :m and idOrdine = 530 and idStab = 1");
q.bindValue(":m","0032110275928");
if( !q.exec() ){
qDebug("error");
return 0;
}
//this fails, the table already exists
q.prepare( "CREATE TABLE test (id INTEGER UNIQUE PRIMARY KEY, firstname VARCHAR(30), lastname VARCHAR(30))" );
if( !q.exec() )
{
qDebug() << q.lastError();
bool res = QSqlDatabase::database().rollback();
qDebug() << res;
return 0;
}
else
{
qDebug() << "Table created!";
QSqlDatabase::database().commit();
}
db.close();
return 0;
}
1 ответ
но что я получил, так это то, что как только вызывается функция отката, запись удаляется.
Выполнение оператора CREATE TABLE вызывает неявную фиксацию для вашего первого запроса (тот, который вы использовали для удаления записи). Следовательно, ваша запись удаляется независимо от того, произошла ошибка CREATE TABLE или нет.
С https://dev.mysql.com/doc/refman/5.6/en/implicit-commit.html,
Операторы, перечисленные в этом разделе (и любые синонимы для них), неявно завершают любую транзакцию, активную в текущем сеансе, как если бы вы выполнили COMMIT перед выполнением оператора.
Также обратите внимание, что вы не можете откатить CREATE TABLE в любом случае, поскольку это один из операторов языка определения данных (DDL), который определяет или изменяет объекты базы данных.