Как лучше справиться с ошибкой sqlite3 corrupt (11) в программе на языке c?

Я видел много статей о проблеме Образ диска базы данных sqlite3 искажен в переполнении стека. Но я хотел бы знать, как справиться с этой ошибкой SQLITE_CORRUPT (код ошибки: 11) в программе C, когда это происходит во время рабочего сервера.

Пример программы

#include <sqlite3.h>
#include <stdio.h>

int insert_records_to_database(sqlite3 *db)
{
   char *err_msg = 0;
   char *sql_in = "INSERT INTO Vehicles VALUES(1, 'maruthi', 5264);"
                "INSERT INTO Vehicles VALUES(2, 'tesla', 5712);"
                "INSERT INTO Vehicles VALUES(3, 'Skoda', 900);"
                "INSERT INTO Vehicles VALUES(4, 'suzuki', 2900);"
                "INSERT INTO Vehicles VALUES(5, 'ferrari', 35000);"
                "INSERT INTO Vehicles VALUES(6, 'Citroen', 2100);"
                "INSERT INTO Vehicles VALUES(7, 'honda', 4140);"
                "INSERT INTO Vehicles VALUES(8, 'fiat', 2160);";

    int rc = sqlite3_exec(db, sql_in, 0, 0, &err_msg);

    if (rc != SQLITE_OK ) {
        if(rc == SQLITE_CORRUPT)
        {
           printf(" SQLITE Database is corrupted :: How to handle");
        }
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(db);

        return 1;
    }
  return 0;
}
int main(void) {

    sqlite3 *db;
    char *err_msg = 0;

    int rc = sqlite3_open("/root/sqlite3/test.db", &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }

    char *sql = "DROP TABLE IF EXISTS Vehicles;"
                "CREATE TABLE Vehicles(Id INT, Name TEXT, Price INT);" ;

    rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
    if (rc != SQLITE_OK ) {
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(db);

        return 1;
    }


    insert_records_to_database(db);


    sqlite3_close(db);

    return 0;
}

-> В приведенной выше программе я выхожу из программы, когда возникает такая ошибка. Но все же поврежденный test.db существует, и на test.db не было предпринято никаких действий. Предположим, что если я хочу использовать одну и ту же БД для вставки записей, в конечном итоге будут возникать те же ошибки, что и образ диска искажен, он не может вставить записи.

-> Как справиться с этим случаем, когда программа постоянно пытается вставить данные в поврежденную базу данных? Есть ли какой-либо эффективный способ решения такой проблемы.

if (rc == SQLITE_CORRUPT)
{
     printf(" SQLITE Database is corrupted :: How to handle");
}

У меня есть работа:

Remove the test.db (or) Re run the program once gain to create test.db freshly.

Сценарий: Если программа работает в бесконечном цикле, база данных (test.db) создается во время запуска программы. После этого, когда программа получает данные от ядра каждые 15 минут и вставляет те же данные в sqlite3 в течение этого времени, если обнаружено повреждение, вставка завершится ошибкой. Как эффективно справиться с этим делом?

Вы можете попробовать dump test.db и сохранить результат в новый файл базы данных и посмотреть, сохранили ли вы что-нибудь полезное. Команда sqlite .dump сгенерирует sql, необходимый для создания новой базы данных.

bruceg 13.09.2018 20:01

.dump покажет команды и ошибку, поскольку диск деформирован. Но мне нужно аккуратно обработать этот случай, когда это происходит во время выполнения.

john 517501 13.09.2018 22:07

Я бы больше сосредоточился на том, чтобы выяснить, что вызывает коррупцию, и исправить это. У вас не должно быть этой проблемы, если ваш код не сломан.

Shawn 14.09.2018 02:02
0
3
651
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для вашего сценария: если программа работает в бесконечном цикле, база данных (test.db) создается во время запуска программы. После этого, когда программа получает данные от ядра каждые 15 минут и вставляет те же данные в sqlite3 в течение этого времени, если обнаружено повреждение, вставка завершится ошибкой. Как эффективно справиться с этим делом?

Создайте свой код, как показано ниже:

Решение 1:

if (rc != SQLITE_OK ) {
        if(rc == SQLITE_CORRUPT)
        {
           printf(" SQLITE Database is corrupted :: How to handle");
        }
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(db);

        # Remove the database file
        remove("test.db");
        # Then exit
        exit(EXIT_FAILURE);
    }

В идеале ваше приложение должно создать новый test.db, если файл не завершается.

Решение 2:

Поддерживать глобальную переменную для непрерывного запуска приложения как

    global_variable =0
     while(!global_variable) { 
       }

Когда возникает эта ошибка, поднимите SIGINT, чтобы корректно завершить работу приложения. У вас должен быть обработчик сигнала для захвата SIGINT и остановки вашего процесса.

   if (rc != SQLITE_OK ) {
        if(rc == SQLITE_CORRUPT)
        {
           printf(" SQLITE Database is corrupted :: How to handle");
        }
        fprintf(stderr, "SQL error: %s\n", err_msg);
        sqlite3_free(err_msg);
        sqlite3_close(db);

        # Remove the database file
        remove("test.db");
        # Raise SIGINT
        raise(SIGINT);
    }


# Register SIGINT
 signal(SIGINT, signal_catchfunc);

void signal_catchfunc(int signal) {
   global_variable=1
   printf("!! signal caught !!\n");
}

Другие вопросы по теме