【问题标题】:why is my transaction not rolling back? Qt Mysql odbc driver为什么我的交易没有回滚? Qt Mysql odbc 驱动程序
【发布时间】:2012-12-04 19:40:15
【问题描述】:

我正在使用 Qt 4.8.3 和 MySQL ODBC 3.51 驱动程序。当我的事务由于第二个表中的重复唯一 ID 而失败时,第一个表中的插入不会回滚。谁能发现错误?

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;
}

【问题讨论】:

  • 表是 Innodb?,你有 autocommit=0(我不确定这个)吗?
  • 好主意,我将不得不检查它的 innodb,这将是一个炫耀...
  • 这些表是 MyISAM,autocommit=1,所以好消息是您发现了我的问题(作为答案发布,我会接受)坏消息是我无法更改它们。我可以在查询中为我的会话设置 autocommit=0 吗? (抱歉,到目前为止我只使用过 innoDB)

标签: c++ mysql qt odbc qtsql


【解决方案1】:

您的表可能是 Myisam,将它们更改为 Innodb 以允许事务。

要更改 AutoCommit(我不确定是否有必要),您可以这样尝试:

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

但这仅适用于当前连接,如果您需要应用到您需要更改数据库变量的所有数据库。

【讨论】:

    猜你喜欢
    • 2019-05-31
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多