更新查询失败,启用事务sqlite3 + android + cocos2dx

时间:2014-09-08 14:44:21

标签: android sqlite transactions sql-update cocos2d-x

我们一直致力于使用cocos2dx的Android应用程序。我们使用sqlite3在设备上本地存储数据。 我们使用c ++代码连接和使用数据库。最近我们使用了交易,它在iOS平台上运行良好 (cocos2dx应用程序是跨平台的)但它在android上失败了。

这很奇怪,因为只有事务中的更新查询失败,如果在循环中运行多个更新,那也是如此。 每个其他查询(插入,删除,选择)在循环中运行良好。我们没有使用多个线程,所以无论运行什么,运行 在主线程上我们都没有打开到数据库的多个连接。如果您关闭,相同的代码 交易。我们不想放弃交易。一种解决方案是使用"插入或替换"查询而不是更新 这是插入或插入删除但我不知道如果表具有外键关系会发生什么。我们可以 如果我们假设数据是正确的,则删除外键约束。

对于每个查询,我们准备一个语句,逐步执行它然后最终确定它,以便即使查询也完成了每个语句 失败。对于pragma设置以及开始和结束事务,我们使用的是包含上述过程的sqlite_exec。

这是一个测试日志: -

09-03 19:36:35.175: D/cocos2d-x debug info(30445): PRAGMA foreign_keys=ON 
09-03 19:36:35.175: D/cocos2d-x debug info(30445): begin transaction 
09-03 19:36:35.180: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): enter loop 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 2 where Test_ID = 133 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.185: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.190: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.190: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 2 where Test_ID = 135 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 2 where Test_ID = 135 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 1 where Test_ID = 140 
09-03 19:36:35.195: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 1 where Test_ID = 140 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 1 where Test_ID = 141 
09-03 19:36:35.200: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 1 where Test_ID = 141 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 1 where Test_ID = 142 
09-03 19:36:35.205: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 1 where Test_ID = 142 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 0 where Test_ID = 144 
09-03 19:36:35.215: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 0 where Test_ID = 144 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 0 where Test_ID = 146 
09-03 19:36:35.220: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 0 where Test_ID = 146 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.225: D/cocos2d-x debug info(30445): update TestTable set ID_Type = 1 where Test_ID = 158 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): Error 14 update TestTable set ID_Type = 1 where Test_ID = 158 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): insert into TestTable(Test_ID) values(1) 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): delete from TestTable where Test_ID = 1 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): Executed 
09-03 19:36:35.230: D/cocos2d-x debug info(30445): select Test_ID, ID_Type from TestTable 
09-03 19:36:35.235: D/cocos2d-x debug info(30445): exit loop 
09-03 19:36:35.235: D/cocos2d-x debug info(30445): rollback 

上面的日志表明它进入循环的位置以及退出循环的位置。在内部循环中,我们以相同的顺序执行更新,插入,删除和选择。 您可以创建任何表并检查它。我不知道出了什么问题。我们检查了以下内容: -

  1. 没有多线程访问。
  2. 同时没有多个连接。
  3. 数据库和database_journal(事务的临时数据库)具有读写权限,否则即使插入和删除也会失败。
  4. 我们尝试开始立即交易
  5. 我们尝试关闭Synchronization pragma
  6. 我们在不同的Android设备(三星和micromax)上测试了
  7. 如果您放弃该事务,则相同的代码可以正常工作。

      

    修改

    你可以在android上试试这个,更新查询失败。如果您只是删除该交易,它将正常工作。您可以尝试插入,删除或选择所有这些工作正常。通常更新执行最大一次然后sqlite错误14"无法打开数据库"来了。

    代码在这里:

    sqlite3 *pSqliteConn = NULL;
        if (sqlite3_open(PATH_OF_DB.c_str(), &pSqliteConn) == SQLITE_OK)
        {
            bool success = true;
    
            char *pErrorMsg = NULL;
            int code = sqlite3_exec(pSqliteConn, "begin transaction", NULL, NULL, &pErrorMsg);
            if (pErrorMsg)
            {
                success = false;
                CCLog("Error %d %s", code, pErrorMsg);
                sqlite3_free(pErrorMsg);
            }
            else
            {
                CCLog("begin transaction");
            }
    
            for (int i = 0; i < 5; i++)
            {
                pErrorMsg = NULL;
                code = sqlite3_exec(pSqliteConn, "update Test_Table set ID_Type = 2 where Test_ID = 144", NULL, NULL, &pErrorMsg);
                if (pErrorMsg)
                {
                    success = false;
                    CCLog("Error %d %s", code, pErrorMsg);
                    sqlite3_free(pErrorMsg);
                }
                else
                {
                    CCLog("Executed");
                }
            }
    
            if (success)
            {
                pErrorMsg = NULL;
                code = sqlite3_exec(pSqliteConn, "commit", NULL, NULL, &pErrorMsg);
    
                if (pErrorMsg)
                {
                    CCLog("Error %d %s", code, pErrorMsg);
                    sqlite3_free(pErrorMsg);
                }
                else
                {
                    CCLog("commit");
                }
            }
            else
            {
                pErrorMsg = NULL;
                code = sqlite3_exec(pSqliteConn, "rollback", NULL, NULL, &pErrorMsg);
    
                if (pErrorMsg)
                {
                    CCLog("Error %d %s", code, pErrorMsg);
                    sqlite3_free(pErrorMsg);
                }
                else
                {
                    CCLog("rollback");
                }
            }
    
            sqlite3_close(pSqliteConn);
        }
        else
        {
            CCLog("connection failed");
        }   
    

    在Android中记录上述代码:

    09-09 17:25:58.384: D/cocos2d-x debug info(12087): begin transaction
    09-09 17:25:58.387: D/cocos2d-x debug info(12087): Executed
    09-09 17:25:58.387: D/cocos2d-x debug info(12087): Error 14 unable to open database file
    09-09 17:25:58.387: D/cocos2d-x debug info(12087): Error 14 unable to open database file
    09-09 17:25:58.388: D/cocos2d-x debug info(12087): Error 14 unable to open database file
    09-09 17:25:58.388: D/cocos2d-x debug info(12087): Error 14 unable to open database file
    09-09 17:25:58.389: D/cocos2d-x debug info(12087): rollback
    

1 个答案:

答案 0 :(得分:0)

消息&#34;无法打开数据库文件&#34;在事务中第一个修改SQL语句表明SQLite无法创建回滚日志文件。

确保您具有对数据库目录的写访问权。