почему моя транзакция не откатывается? odbc-драйвер Qt Mysql

Я использую Qt 4.8.3 и драйвер MySQL ODBC 3.51. Когда моя транзакция терпит неудачу из-за повторяющегося уникального идентификатора во второй таблице, вставка в первую таблицу не откатывается. Может ли кто-нибудь заметить ошибку?

struct Property  //see OMG's Property Service
{
    std::string name;
    boost::any value;
    Property();
    Property(const std::string &inName, const boost::any &inValue):name(inName),value(inValue){}

};

Property myFunction(QSqlDatabase &db, int amount)
{
    assert(db.driver()->hasFeature(QSqlDriver::Transactions) == true);
    db.transaction();
    QSqlQuery query(db);
    Property ret("MyPropertyTag",0);
    try{
        query.exec("LOCK TABLES table1 WRITE, table2 WRITE");
        if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); }
        for(int i=0;i<amount;i++)
        {
            query.exec("INSERT INTO table1 (someUniqueValue, newestId, Created) VALUES ('"+QString::number(i)+"', '1', NOW())");
            if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); }
            query.exec("SELECT id FROM table1 WHERE someUniqueValue = '"+QString::number(i)+"'");
            if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); }
            if(query.next() == false)   { throw std::exception("no result for insert id"); }
            auto Id1 = query.value(0).toString();

            query.exec("INSERT INTO table2 (table1_id, Changed, Created) VALUES ('"+Id1+"', NOW(), NOW())");
            if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); }
            query.exec("SELECT Id, table1_id FROM table2 ORDER BY Id DESC LIMIT 1");
            if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); } //lets say this throws
            if(query.next() == false || query.value(1).toString() != Id1)   { throw std::exception("no result for inserted id"); }
            auto Id2 = query.value(0).toString();

            query.exec("UPDATE table1 SET newestId = '"+Id2+"' WHERE Id = '"+Id1+"'");
            if(query.lastError().isValid()) { throw std::exception(query.lastError().text().toAscii()); }
        }
        db.commit();
        ret.value = amount;
    } catch(std::exception &e) {
        query.finish();
        db.rollback();
        ret.value = std::string("error:") + e.what();
    }
    query.exec("UNLOCK TABLES");
    query.finish();
    return ret;
}

person odinthenerd    schedule 04.12.2012    source источник
comment
таблицы Innodb?, у вас есть autocommit=0 (я не уверен в этом)?   -  person jcho360    schedule 04.12.2012
comment
хорошая идея, мне нужно будет проверить, является ли это innodb, это было бы шоу-стоппером...   -  person odinthenerd    schedule 04.12.2012
comment
таблицы MyISAM с autocommit = 1, так что хорошие новости, что вы нашли мою проблему (напишите как ответ, и я приму), плохие новости: я не могу их изменить. Могу ли я установить autocommit=0 для своего сеанса в запросе? (извините, я пока работал только с innoDB)   -  person odinthenerd    schedule 05.12.2012


Ответы (1)


Ваши таблицы, вероятно, являются Myisam, изменили их на Innodb, чтобы разрешить транзакции.

Чтобы изменить AutoCommit (я не уверен, что это необходимо), вы можете попробовать это так:

mysql> SET autocommit=0;
Query OK, 0 rows affected (0.00 sec)

но это будет работать только с текущим соединением, если вам нужно применить ко всем БД, вам нужно изменить переменные БД.

person jcho360    schedule 04.12.2012