Восстановление битой истории Skype (main.db)

    Skype database crashПромучавшись в очередной раз над восстановлением побившейся базы, решил набросать краткую инструкцию, как мне удалось вернуть почти всю историю сообщений скайпа. Знатоки sqlite3 приглашаются для написания более лучших способов, чем я нащупал наугад.

    Предыстория


    Переустановил ОС Win7, установил skype (6-й), привычно скопировал всю папку профиля из старого:
    %AppData%\Roaming\Skype\мой_профиль\
    в новое место.

    Запускаю скайп и вдруг он виснет на автовходе. После повторного запуска вижу приглашение войти. Вхожу — все контакты на месте, а сообщений — практически нигде нет. Только в некоторых групповых чатах сохранились. Вся личная переписка, коей скопилось немало — исчезла. Проделал N(^k) попыток копировать базу данных, удаляя файлы блокировок, is-corrupt и прочие. Скайп ругается, что с базой проблемы, затем просит перезайти — после чего сообщений нет.
    Погуглив, нашел хабро-посты про экспорт сообщений, угон аккаунтов и т.п. Ага, значит sqlite! Это обнадёживает.

    Инструменты и материалы
    Вам понадобится:
    • уцелевшая копия базы main.db до того, как её «открыл» новый скайп, начисто затерев данные (или возьмите файл main.corrupt, если копии не оказалось)
    • SQLite Manager
    • sqlite3 command line (оптимально — работать в ней под *nix)
    • Notepad++ или любой другой редактор, который не гробит UTF-8 файлы.
    • *nix shell (какой-нибудь сервер с linux/ubuntu/..., т.к. самый важный последний шаг под виндоуз может не сработать)


    Анализируем базу


    Информация для админов, программистов и опытных пользователей
    1. Качаем SQLite Manager (спасибо за ссылку, minamoto).

    2. Открываем файл main.db (около 150 мегабайт у меня).

    3. База данных — Проверка целостности — Полная проверка.

    Проверка целостности базы данных с помощью «PRAGMA integrity_check».
    Результат: НЕ УСПЕШНО. Чтобы увидеть ошибки, выполните оператор «PRAGMA integrity_check» во вкладке «Выполнить запрос».


    4. Выполняю указанную команду, получаю много страшных буков:

    "*** in database main ***
    On tree page 5482 cell 13: Rowid 262638 out of order (max larger than parent max of 255232)
    On tree page 22553 cell 8: Rowid 255233 out of order (min less than parent min of 262638)
    On tree page 5601 cell 10: Rowid 270500 out of order (max larger than parent max of 255358)
    On tree page 9610 cell 10: Rowid 255359 out of order (min less than parent min of 270500)
    On tree page 25320 cell 145: 2nd reference to page 5482
    On tree page 25320 cell 145: Child page depth differs
    On tree page 25320 cell 146: Child page depth differs
    On tree page 25827 cell 290: 2nd reference to page 5601
    On tree page 25827 cell 290: Child page depth differs
    On tree page 25827 cell 291: Child page depth differs
    On tree page 8955 cell 0: 2nd reference to page 28154
    On tree page 27843 cell 0: 2nd reference to page 28136
    Page 5335 is never used
    Page 5344 is never used
    Page 5369 is never used
    … тут много таких is never used
    Page 28212 is never used"
    «wrong # of entries in index IX_Messages_remote_id»
    «wrong # of entries in index IX_Messages_timestamp_convo_id_type»
    «wrong # of entries in index IX_Messages_timestamp_chatname»
    «wrong # of entries in index IX_Messages_call_guid»
    «wrong # of entries in index IX_Messages_convo_id_timestamp_consumption_status_sending_status»
    «rowid 95101 missing from index IX_Contacts_buddystatus»
    «rowid 103110 missing from index IX_Contacts_buddystatus»
    «rowid 209626 missing from index IX_Contacts_buddystatus»


    Кстати, в других утилитах при попытке просмотреть таблицы сообщений, часто получал такое: "the database disk image is malformed".


    Поскольку я не знаток sqlite и не горю желанием изучать каждую ошибку, поступаем просто.

    Лечение


    Гуглим как дампить базы sqlite, получается примерно так:

    1. Скачать sqlite3 command line для Windows или «apt-get install sqlite3» для *nix. Я сначала экспериментировал под виндой, но впоследствии пришлось перейти в консоль Linux, т.к. виндовая sqlite3 не совсем хорошо себя показала.

    2. Под Windows копируем sqlite3.exe в папку с копией базы (архивной с предыдущей винды, которую ещё не испортил скайп). Затем запускаем cmd (Пуск > выполнить).
    Под линуксом — просто выполняем:

    cd путь-к-папке-с-базой-и-sqlite3.exe
    sqlite3 main.db .dump>>myDumpSQLite.sql

    (Именно «main.db[пробел].dump, не перепутайте)

    3. Открываем файл myDumpSQLite.sql в нормальном текстовом редакторе, например Notepad++. В самом конце файла у меня стояла команда:

    ROLLBACK;

    Кто знаком с SQL, знает зачем нужно удалить эту последнюю строку в файле и вместо неё написать:
    COMMIT;

    (Можно и вовсе отказаться от транзакции, но тогда будет очень долгий импорт данных в новую базу.)

    4. Создаём новую, чистую базу из файла myDumpSQLite.sql (рекомендуется под Linux).

    sqlite3 main-recovered.db <myDumpSQLite.sql
    При этом могут возникать сообщения об ошибках
    У меня это были примерно такие:

    Error: near line 329619: PRIMARY KEY must be unique
    Error: near line 329620: PRIMARY KEY must be unique
    Error: near line 329621: PRIMARY KEY must be unique
    Error: near line 329622: PRIMARY KEY must be unique
    ... ещё пару десятков таких сообщений


    Благодаря тому, что мы сделали COMMIT в конце файла — ошибки будут проигнорированы. Теоретически, что-то потеряется (какие-то одиночные сообщения, может даже какой-то чат пропадёт). Но это ничто по сравнению с потерей всей базы, которую предлагает Microsoft.


    Полученный файл main-recovered.db должен весить примерно столько же, сколько и sql-файл (у меня получилось 123Мб). Если пропустить шаг 3 или что-то пойдёт не так — получите пустой бесполезный файл.
    Windows кака. © КЭП
    У меня получилось только под Linux, так что если под Windows не работает, а linux вам не знаком — ищите нужных друзей). Виндовая sqlite3 выдала:
    Error: incomplete SQL: INSERT INTO „Contacts“ VALUES(951.......



    5. Копируем полученный файл в папку %AppData%\Roaming\Skype\мой_профиль\ под именем main.db, заменяя поломавшуюся (Skype должен быть выключен).

    6. Запускаем Skype. Вводим логин и пароль (у меня автоматом зашло).

    7. PROFIT!!! Все сообщения вернулись!
    Восстановленная 
история Skype
    Знаете лучший способ? — приглашаю в комментарии.
    Возможно есть более грамотный способ восстановления БД. Я даже нашел Кое-какую жадную утилиту, но она мне не помогла (может надо было денег дать?). Ещё пробовал SkypeHistoryReader, Kudos Chat Search, sqlite maestro и всяко-разно.
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 24
    • 0
      Да, похоже, «PRAGMA integrity_check» — это самая полная команда для восстановления данных, и если она не помогает — то единственный способ — это дампить базу и вытаскивать данные построчно.
      Похоже, команда SQLite считает свой продукт очень надежным, и не стремится разрабатывать инструменты на случай физического повреждения базы.
      Хорошо, что дамп получилось создать, хоть и с ошибками.
      Можно еще поковырять полученный дамп на предмет тех строчек, на которые ругался импортер — если это какая-то конечная таблица, типа «CallMembers» или «Messages», то primary key можно заменить на любой незанятый, если табличка, на которую идет ссылка — типа «Conversations», то тут можно посмотреть нижележащую табличку на предмет ссылок, ведущих «в никуда», и попытаться угадать, какой primary key в табличке должен быть.
      Можно еще глубже залезть и посмотреть содержимое поврежденных страниц (кстати, интересно, есть ли у sqlite инструменты для такого низкоуровневого доступа, типа DBCC PAGE в MS SQL), но это уже перфекционизм — времени уйдет много, скорее всего ради нескольких потерянных сообщений или вообще ненужных в данной ситуации индексов.
      • 0
        У меня нет цели восстановить всё до последнего сообщения. Мне прежде всего было важно вообще получить доступ к своей истории, т.к. некоторые диалоги мне важны чаще для восстановления хронологии событий, чем даже для их сути. Поэтому, конечно, настолько сильно закапываться в тонкости Sqlite смысла не был о. Я вообще рад, что получилось малой кровью (хотя это заняло несколько часов) всё вернуть. Но в целом, я согласен с тем фактом, что разработчик базы данных первым же делом должен заботиться об инструментах низкоуровневого восстановления. И уж, тем более, я удивлён — почему за много лет существования Skype там до сих пор нет инструмента автоматического резервного копирования (не говоря уж о таком простом способе быстрого восстановления БД).
      • +6
        Интересный заголовок. «Восстановление битой истории Skype» — «Восстановление истории skype с помощью биты» :)
        • +4
          Название главы в учебнике по терморектальному криптоанализу )
        • +1
          Да, я как-то задался целью сделать так, чтобы можно было видеть какое сообщение пользователь отредактировал или удалил. Оказалось достаточно просто — нужно всего-то добавить триггер на update и delite. База не шифрованная — простора для творчества хоть отбавляй.
          • 0
            А я просто брал id'ы всех чатов, потом по ним сообщения и записывал в .txt файлы. Сколько всего вспомнил, перечитывая…
            • 0
              Всё-таки хранить в текстовом формате не самый удобный способ, особенно когда база уже за 150Мб перевалила. Я сначала хотел конвертнуть всё в привычный мне MySQL, но потом обнаружил, что база битая и не всё так просто.
              • 0
                У меня база весила в тот момент 178 мб. Я тоже в MySQL хотел перевести, но увидел тучу ошибок, которые, кстати, удалось исправить и перенести бд на мускул. А дальше уже все легко и просто.
            • 0
              привычно скопировал всю папку профиля из старого
              Копирование подразумевает наличие исходной рабочей копии, видимо имелось в виду перемещение. Но даже при перемещении файла с другого раздела исходный вариант можно восстановить. В общем, надеюсь теперь вы относитесь к той группе людей, которые уже делают бекапы.
              • 0
                Копировал. У меня бекап на другом винте, т.к. я переезжал на другой компьютер. Ну и есть несколько более старых архивов профиля, но полгода минимум потери данных — не лучший вариант.
                • 0
                  Так зачем восстанавливать битую базу, когда можно взять её из неповреждённого бекапа?
                  • 0
                    Затем, что бекап от мая 2012 года. Это 6 месяцев назад — меня не устраивала такая потеря истории.
                    • 0
                      Читаем вашу предысторию:
                      Переустановил ОС Win7, установил skype (6-й), привычно скопировал всю папку профиля из старого: %AppData%\Roaming\Skype\мой_профиль\ в новое место. Запускаю скайп и вдруг он виснет на автовходе. После повторного запуска вижу приглашение войти. Вхожу — все контакты на месте, а сообщений — практически нигде нет.
                      Мои действия в таком случае:

                      1) Повторно копируем профиль вместо повреждённого, если на входе не подвисает и историю видно — готово.

                      2) Если происходит повторное зависание и повреждение профиля, ставим ту же версию скайпа, которая работала с профилем, и после логина средствами самого скайпа обновляем её до последней версии. Это на случай, если программа установки вносит изменения в базу, без которых программа виснет (подмена профиля от 5-й версии на 6-ю — нестандартная ситуация, разработчики предполагают обычное обновление).

                      Вы ясно написали, что переустановили систему и скопировали профиль обратно, значит он уже свежий. При чём здесь старый полугодовой архив — не понятно.
                      • 0
                        Не хочу вступать с Вами в длительную полемику. Объясню просто:
                        1. Есть рабочая база полугодовой давности.
                        2. Есть свежая копия профиля с предыдущей системы с побившейся базой.

                        Ваши пункты 1 и 2 совмещены вначале топика в фразе:
                        «Проделал N(^k) попыток копировать базу данных, удаляя файлы блокировок, is-corrupt и прочие. »
                        • 0
                          Теперь понятно. Мне было не очевидно, что у вас повреждена не копия, а исходная база со старого компьютера, и при этом там скайп работал.
              • 0
                Спасибо, автор. Из вашего сообщения я почерпнул ценную информацию о том, что базу Скайпа можно анализировать сторонним ПО. Главным образом это имеет ценность в виде экспорта сообщений в какой-нибудь формат, чтобы можно было оперировать ими более свободно, чем средствами Skype.
                • +1
                  Это исследовали до меня, почитайте по хабу skype пару постов назад.
                  Ссылки в топике приведены:
                  habrahabr.ru/post/160315/
                  habrahabr.ru/post/158545/

                  База полностью открыта — действительно можно много добавить возможностей, включая одновременный доступ посторонним ПО, резервное копирование или конвертацию в MySQL, где уже даже в phpMyAdmin появляется масса возможностей по разнообразной фильтрации истории.
                  Ну и, конечно, вопрос безопасности тут в полный рост.
                • 0
                  Вся история переписок хранится на серверах майкрософта и автоматически подгружается при входе в скайп. Не понял суть топика.

                  А нашёл статью потому, что искал, каким именно образом закодирована переписка в файле main.db.
                  • 0
                    yaptro, статья от 2012 года. И насколько мне известно, в скайп подгружается информация не с серверов майкрософта, а из клиентов контакт-листа, находящихся в сети. Если контакт не онлайн — переписка с ним не подгружается. Ну ещё с недавних пор — из пуш-нотификаций приходит на мобильные клиенты.

                    И переписка там не закодирована, там просто sqlite база данных. Полностью открытая. Если конечно ничего не поменялось за последний год.
                    • 0
                      Однако, удаляя базу данных, все разговоры загружаются заново. И иногда собеседники не в сети.

                      Да, sqlite база данных. Осталось только разобраться, как с ней работать (как извлечь информацию — получить её в текстовом виде). Может, кто поможет?
                      • 0
                        Возможно, собеседники просто не хотят, чтобы вы их видели :)

                        Первая ссылка в посте — habrahabr.ru/post/160315/ — на мой пост о том, как с ней работать.
                        • 0
                          Нет, не все разговоры загрузятся. Если у вас рабочая история переписки за 3-5 лет, то синхронизация подгрузит пару месяцев назад, но далеко не факт, что всю историю.
                          • 0
                            В статье непосредственно указан инструмент подключения к sqlite базе. Это плагин к Firefox, addons.mozilla.org/ru/firefox/addon/sqlite-manager/
                            • 0
                              Спасибо. Я пользовался sqlitebrowser — оконным приложением. Всё скопировал.

                              Нет, не все разговоры загрузятся. Если у вас рабочая история переписки за 3-5 лет, то синхронизация подгрузит пару месяцев назад, но далеко не факт, что всю историю.


                              Подгрузилась вся база с того момента, когда я её последний раз чистил.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.