2012-12-04 2 views
0

Qt 4.8.3 및 MySQL ODBC 3.51 드라이버를 사용하고 있습니다. 두 번째 테이블의 고유 ID가 중복되어 트랜잭션이 실패하면 첫 번째 테이블의 삽입이 롤백되지 않습니다. 누구든지 오류를 발견 할 수 있습니까?왜 내 거래가 롤백되지 않습니까? Qt Mysql ODBC 드라이버

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

테이블은 Innodb입니까?, 자동 커밋 = 0입니까 (이 것에 대해서는 확실하지 않습니다)? – jcho360

+0

좋은 생각, 그 showodopper 것입니다 그 innodb 경우 체크해야 할 것입니다 ... – odinthenerd

+0

테이블 자동 응답 = 1, 그래서 내 소식 (대답으로 게시하고 받아 들일 것입니다) 좋은 소식을 발견 좋은 소식 MyISAM 있습니다 나쁜 소식 나는 그들을 바꿀 수 없다. 쿼리에서 내 세션에 대해 autocommit = 0을 설정할 수 있습니까? (미안하지만 지금까지 innoDB로만 작업했다.) – odinthenerd

답변

0

귀하의 테이블은 아마도 Myisam이며, Innodb로 변경되어 트랜잭션을 허용합니다.

당신이 그것을 이런 식으로 시도 할 수 있습니다 (나는 그것이 필요하다면 확실하지 않다) 자동 커밋을 변경하려면 :

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

을하지만 모두에 적용해야하는 경우이는 현재 연결 만 작동됩니다 당신은 DB 변수를 변경해야합니다.