我正在使用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;
}
答案 0 :(得分:0)
你的桌子可能是Myisam,将它们改为Innodb以允许交易。
要更改AutoCommit(我不确定是否有必要),您可以这样尝试:
mysql> SET autocommit=0;
Query OK, 0 rows affected (0.00 sec)
但是,如果您需要应用所有需要更改数据库变量的数据库,那么这只适用于当前连接。