Не удалось открыть файл базы данных sqlite
в Linux и macOS вы можете сделать что-то подобное, например, если заблокированный файл-это развитие.дБ:
эта команда покажет какой процесс блокирует файл:
просто убейте процесс.
. И ваша база данных будет разблокирована.
Я вызвал блокировку моей БД sqlite путем сбоя приложения во время записи. Вот как я это исправил:
на этой странице не объясняется, как SQLite решает, что что-то в вашем процессе держит блокировку и какие условия могут привести к ложному срабатыванию.
удаление файла-journal звучит как ужасная идея. Это позволяет sqlite откатить базу данных в согласованное состояние после сбоя. Если вы удалите его, пока база данных находится в несогласованном состоянии, вы останетесь с поврежденной базой данных. Цитирование страницы из сайт sqlite:
Если сбой или потеря питания происходит и горячий журнал остается на диске, важно, чтобы исходный файл базы данных и горячий журнал остались на диске с их исходными именами, пока файл базы данных не будет открыт другим процессом SQLite и откат. [. ]
мы подозреваем, что общий режим сбоя для восстановления SQLite происходит следующим образом: происходит сбой питания. После восстановления питания благонамеренный пользователь или системный администратор начинает искать повреждения на диске. Они видят файл своей базы данных с именем " важно.данные." Возможно, этот файл им знаком. Но после крушения есть еще и горячий журнал по имени " важно.data-journal". Затем пользователь удаляет горячий журнал, думая, что они помогают очистить систему. Мы не знаем другого способа предотвратить это, кроме обучения пользователей.
откат должен произойти автоматически при следующем открытии базы данных, но он завершится ошибкой, если процесс не сможет заблокировать базу данных. Как говорили другие, одна из возможных причин этого заключается в том, что в настоящее время он открыт для другого процесса. Другая возможность-устаревшая блокировка NFS, если база данных находится на томе NFS. В этом случае обходным путем является замена файла базы данных новой копией, которая не заблокирована на сервере NFS (база данных mv.дБ оригинал.дБ; СР оригинала.база данных БД.децибел.) Обратите внимание, что SQLite FAQ рекомендует соблюдать осторожность в отношении параллельного доступа к базам данных на томах NFS из-за ошибочных реализаций блокировки файлов NFS.
Я не могу объяснить, почему удаление файла журнала позволит вам заблокировать базу данных, которую вы не могли раньше. Заключаться в том воспроизводимый?
кстати, наличие файла-journal не обязательно означает, что произошел сбой или что есть изменения, которые нужно откатить. Sqlite имеет несколько различных режимов журнала, и в режимах PERSIST или TRUNCATE он всегда оставляет файл-journal на месте и изменяет содержимое, чтобы указать, есть ли частичные транзакции для отката.
Если процесс имеет блокировку на БД SQLite и аварийно завершает работу, БД остается заблокированной навсегда. Вот в чем проблема. Дело не в том, что какой-то другой процесс заблокирован.
Если вы хотите удалить ошибку "база данных заблокирована", выполните следующие действия:
- скопируйте файл базы данных в другое место.
- замените базу данных копируемой базой данных. Это разыменует все процессы, которые обращались к вашему файлу базы данных.
файлы БД SQLite-это просто файлы, поэтому первым шагом было бы убедиться, что он не доступен только для чтения. Другое дело, чтобы убедиться, что у вас нет какого-то GUI SQLite DB viewer с открытой БД. Вы можете открыть БД в другой оболочке, или ваш код может открыть БД. Обычно вы увидите это, если другой поток или приложение, такое как браузер базы данных SQLite, имеет открытую для записи БД.
У меня только что была эта проблема, используя базу данных SQLite на удаленном сервере, хранящуюся на монтировании NFS. SQLite не удалось получить блокировку после того, как сеанс удаленной оболочки, который я использовал, разбился во время открытия базы данных.
рецепты восстановления, предложенные выше, не работали для меня (включая идею сначала переместить, а затем скопировать базу данных обратно). Но после копирования его в систему, отличную от NFS, база данных стала полезной, а не данные, похоже, были потеряны.
нашел документация различных состояний блокировки в SQLite, чтобы быть очень полезным. Майкл, если вы можете выполнять чтение, но не можете выполнять запись в базу данных, это означает, что процесс получил зарезервированную блокировку в вашей базе данных, но еще не выполнил запись. Если вы используете SQLite3, есть новая блокировка под названием PENDING, где больше не разрешено подключать процессы, но существующие соединения могут выполнять чтения, поэтому, если это проблема, вы должны посмотреть вместо этого.
эта ошибка может быть вызвана, если файл находится в удаленной папке, например в общей папке. Я изменил базу данных на локальный каталог, и она работала отлично.
моя блокировка была вызвана сбоем системы, а не процессом зависания. Чтобы решить эту проблему, я просто переименовал файл, а затем скопировал его обратно в исходное имя и местоположение.
используя оболочку linux, которая была бы.
у меня есть такая проблема в приложении, доступ к SQLite из 2 соединений - один был только для чтения и второй для записи и чтения. Похоже, что соединение только для чтения заблокировало запись из второго соединения. Наконец, оказывается, что требуется доработать или, по крайней мере, сбросить подготовленные операторы сразу после использования. До тех пор, пока подготовленная инструкция не будет открыта, она вызывала, чтобы база данных была заблокирована для записи.
НЕ ЗАБУДЬТЕ Звоните:
некоторые функции, такие как индексация, могут занять очень много времени - и он блокирует всю базу данных во время ее запуска. В таких случаях он может даже не использовать файл журнала!
таким образом, лучший/единственный способ проверить, заблокирована ли ваша база данных, потому что процесс активно пишет в нее (и, таким образом, вы должны оставить его в покое, пока он не завершит свою работу), чтобы md5 (или md5sum на некоторых системах) файл дважды. Если вы получаете другую контрольную сумму, база данных записывается, и вы действительно действительно не хотите убивать -9 этот процесс, потому что вы можете легко получить поврежденную таблицу/базу данных, если вы это сделаете.
Я повторю, потому что это важно - решение состоит не в том, чтобы найти программу блокировки и убить ее - это найти, есть ли в базе данных блокировка записи по уважительной причине, и идти оттуда. Иногда правильным решением является просто перерыв на кофе.
единственный способ создать эту заблокированную, но не записываемую ситуацию-это если ваш программа работает BEGIN EXCLUSIVE , потому что он хотел сделать некоторые изменения таблицы или что-то еще, то по какой-то причине никогда не отправляет END впоследствии, и этот процесс никогда не заканчивается. Все три условия, которые выполняются, крайне маловероятны в любом правильно написанном коде, и поэтому 99 раз из 100, когда кто-то хочет убить -9 их процесс блокировки, процесс блокировки фактически блокирует вашу базу данных по уважительной причине. Программисты обычно не добавляют BEGIN EXCLUSIVE состоянии, если им действительно нужно, потому что это предотвращает параллелизм и увеличивает жалобы пользователей. SQLite сам добавляет его только тогда, когда это действительно нужно (например, при индексировании).
Информация: я работаю над проектом с использованием sqlite3 базы данных. Я написал тестовую программу, которая запускает и передает ей базу данных:
Программа модульного тестирования может выполнить db без каких-либо проблем. Но когда я на самом деле использую программу, передающую ей то же местоположение, я получаю ошибку ниже:
OperationalError: невозможно открыть файл базы данных
Я пробовал делать это с помощью:
В трех случаях я получил вышеуказанную ошибку. Самым неприятным моментом должен быть тот факт, что unittest может сделать это просто отлично, а сама программа - нет.
Какие-нибудь подсказки относительно того, что происходит на земле?
В моем случае решение было использовать абсолютный путь, чтобы найти существующий файл:
Я не знаю, почему это исправление работает: путь содержал только символы ASCII и без пробелов. Тем не менее это имело значение.
Для справки: Windows 7, Python 3.6.5 (64-разрядная версия).
Мне не удалось воспроизвести проблему на другом компьютере (также Windows 7, Python 3.6.4 64-bit), поэтому я понятия не имею, почему это исправление работает.
В Unix я получил эту ошибку при использовании ярлыка ~ для пользовательского каталога. Изменение на /home/user устранило ошибку.
Моя причина была очень глупой. Я поместил файл manage.py на терминал, чтобы он работал по полному пути. И я изменил название папки проекта. Поэтому теперь программе не удалось найти файл с предыдущими данными и, следовательно, с ошибкой.
Убедитесь, что вы перезапустите программное обеспечение в таких случаях.
для более ясного полного пути, если вы не поняли его
Единственное, что вам нужно сделать, это создать папку (так как она еще не существует), программа создаст только файл базы данных. Это действительно сработало для меня!
Это сработало для меня:
Примечание: двойная косая черта в полном пути
Использование python v2.7 на Win 7 enterprise и Win Xp Pro
Надеюсь, это кому-то поможет.
Одной из причин может быть запуск кода по пути, который не совпадает с указанным вами путем для базы данных. Например, если в вашем коде у вас есть:
И вы запускаете код внутри folder_A или других мест, где нет folder_A , это вызовет такую ошибку. Причина в том, что SQLite создаст файл базы данных, если он не существует, а не в папке.
Еще один способ обойти эту проблему - обернуть вашу соединительную команду в выражение try-except и создать каталог, если он вызывает sqlite3.OperationalError .
Из os import mkdir import sqlite3 как облегченный
Это определенно проблема с разрешениями. Если кто-то получает эту ошибку в Linux, убедитесь, что вы запускаете команду с sudo , поскольку файл, скорее всего, принадлежит пользователю root. Надеюсь, это поможет!
Для любого, у кого есть проблема с воздушным потоком, связанным с этой проблемой.
В моем случае я инициализировал поток воздуха в /root/airflow и запустил его планировщик как root . Я использовал параметр run_as_user , чтобы выдать себя за веб пользователь во время выполнения экземпляров задач. Однако поток воздуха всегда не вызывал мою группу доступности базы данных со следующими ошибками в журналах:
Я также обнаружил, что после запуска DAG вручную новый каталог ресурсов воздушного потока автоматически создается в /home/web . Я не совсем уверен в этом, но я заставляю его работать, удаляя все ресурсы воздушного потока из /root , повторно инициализируя базу данных воздушного потока в /home/web и запуская планировщик как web в разделе :
Если вы хотите попробовать этот подход, мне может потребоваться сделать резервную копию ваших данных, прежде чем что-либо делать.
Если это происходит случайно после правильного доступа к вашей базе данных (и никакие настройки не изменились), это может быть результатом поврежденной базы данных .
Я получил эту ошибку после попытки записи в мою базу данных из двух процессов одновременно , и она, возможно, повредила мой файл db.sqlite3.
Мое решение состояло в том, чтобы вернуться к предыдущей фиксации до того, как произошло повреждение.
1) Проверьте путь к вашей базе данных, проверьте ваши settings.py
Иногда не будет NAME ': os.path.join (BASE_DIR,' project.db '),
2) Убедитесь в разрешении и праве собственности на папку назначения
Это сработало для меня,
Запустил ошибку в Windows, добавил assert os.path.exists, дважды проверил путь, запустил скрипт от имени администратора, ничего не помогло.
Оказывается, если вы добавите свои папки в Защиту от вымогателей Защитника Windows, вы больше не сможете использовать для записи другие программы, если вы не добавите эти программы в белый список доступа к контролируемым папкам.
Решение - проверьте, была ли ваша папка добавлена в Ransomware Protection Защитника Windows, и удалите ее для более быстрого исправления.
Я столкнулся с той же проблемой в Windows 7. Моя база данных была test , и я получил ошибку:
Я заменил test на test.db и все прошло гладко.
Столкнулся с этой проблемой при попытке создать индекс для совершенно правильной базы данных. Оказывается, он выдаст эту ошибку (в дополнение к другим причинам, описанным здесь), если переменная / каталог sqlite temp_store_directory недоступна для записи.
Решение: замените temp_store_directory на c.execute(f'PRAGMA temp_store_directory = ""') . Обратите внимание, что эта прагма устарела, и я пока не уверен, какая замена будет ,
Убедитесь, что вы не редактируете файл settings.py при попытке запустить syncdb, вы получите ту же ошибку .
In the connection string i have defined password as "mypassword" if i remove this password everything is working well but when i use password clause, it gives me error in connection.open() syntax that
I searched on net and found some version issue but i am using version 3 only as i stated in connection string i also tried removing the "version=3" but problem remains the same.
I am doing this first time, what is the solution of it?
I got this error message because I tried to open the db file with sqlite but what i should have used is sqlite3 .
3 Answers 3
When you specify a password in the connection string, and the database already exists, SQLite assumes the database is encrypted and will try to decrypt it with said password. If you haven't set a password on the database yet, this will result in the "file is encrypted" error, because the supplied password can't be used to decrypt an unencrypted database.
You can either delete the database, and SQLite will create a new encrypted database using the password in the connection string. Or, you can encrypt your existing database using the ChangePassword() method:
+1, thanks a lot it's working but only first time it worked flawlessly but when i run the application second time it it again showing the same exception on con.open that "File opened that is not a database file file is encrypted or is not a database"
@harhar please outline the steps you took to encrypt your database. If you used the ChangePassword() method, you'll want to remove it from subsequent calls.
after con.Open(); i write con.ChangePassword("password"); and after working with it i do con.ChangePassword(""); and finally con.Close(); is it wrong ?
@harhar if you want to specify the password in the connection string, then call ChangePassword("mypassword") one time to set the encryption on the database (and don't call it again unless you really want to change the password). Remove the call to ChangePassword("") entirely, because that's removing the encryption from your database - which is why the next time you try to open it with the connection string password you get the "file is encrypted" error again.
I didn't get why you would get the error that the "file is encrypted" again when you try conn.ChangePassword("") , if you are removing encryption by blanking the password. But if you call the DB with a password in the string, I found that is what happens - the DB is probably trying to decrypt with that password, and encryption is removed when the password is removed. conn.SetPassword("something"); conn.Open() , and call it with that password in the connection string. To change it, you could blank it w/change, but then you have to remove the Password parameter from the connection string.
2Toad's answer is mostly correct, but I wanted to add my own because there are some clarifications to be made. As 2Toad said, this is correct:
When you specify a password in the connection string, and the database already exists, SQLite assumes the database is encrypted and will try to decrypt it with said password. If you haven't set a password on the database yet, this will result in the "file is encrypted" error, because the supplied password can't be used to decrypt an unencrypted database.
But this error can also happen if you try to use conn.SetPassword("something") after you already had another one in the connection string. Or if you do conn.ChangePassword("somethingelse") , but still have Password=something in the connection string.
There are several scenarios to consider:
- The database has had a password applied, and it is in the connection string.
- You have a password in the connection string, but the database does not have one applied, or the password in the string does not match the DB.
- The database has never had a password, and you want to change it.
- The database has had a password, and you want to change it.
So the code 2Toad provided to perform conn.ChangePassword("somethingelse") is only half-correct and doesn't take into account where you are, what else you've done, and what you want to do in the future. If you have an existing password and you want to change it, this is correct, but you also have to be sure the connection string is updated afterwards, or subsequent connections will fail with the file is encrypted error.
This scenario happens if you blank the password using conn.SetPassword("") and then try conn.ChangePassword("somethingelse") without first connecting to the database without the Password=something in the connection string. That Password=something would have to be removed from the connection string, because the password has been removed programmatically from the DB and the DB will try connecting with that. If it's not removed from the connection string at the same time as it's removed from the DB programmatically, you'll get the same file is encrypted error.
Because I started out by doing a conn.SetPassword("something") in the very beginning when I didn't have a password applied (and I believe this is the way to do that), I cannot verify the following without creating another SQLite DB, but I do not believe you can call conn.ChangePassword("something") if you never had a password in the first place. You should do conn.SetPassword("something") for the initial set, and then put Password=something in your connection string.
The way I did a change of a password was where I did conn.ChangePassword("somethingelse") only after doing conn.SetPassword("") and clearing the Password=something from the connection string:
This worked out fine. I suppose you can also not clear it from the connection string and simply do conn.ChangePassword("somethingelse") , and then add Password=somethingelse to your string, afterwards:
Personally, I store the password as encrypted in an app (web) .config file, and call it into a variable in my application onload and dynamically build my connection string from it.
Info: I'm working on a project using sqlite3 database. I wrote a test program that runs and passes it the database:
The unit test program can make the db without any problem. But, when I actually use the program passing the same location to it, i got below error:
OperationalError: unable to open database file
I've tried doing it with:
In three cases, I got the above error. The most frustrating part has to be the fact that the unittest can do it just fine, but the actual program can't.
Any clues as to what on earth is going on?
Is that the full path? Are you sure you aren't passing the path via environment variables or ~ or some other short form?
Came across the same error, turned out i had a colon ' : ' in the file name and sqlite didn't like it. Took it out, works like a charm.
19 Answers 19
Primary diagnosis: SQLite is unable to open that file for some reason.
Checking the obvious reasons why, and in approximate order that I recommend checking:
- Is the program running on the same machine as you're testing it?
- Is it running as you (or at least the same user as you're testing it as)?
- Is the disk containing /tmp full? (You're on Unix, so use df /tmp to find out.)
- Does the /tmp/cer directory have “odd” permissions? (SQLite needs to be able to create additional files in it in order to handle things like the commit log.)
- Is the unit test code still using that database? (Concurrent opens are possible with a modern-enough SQLite and when in the right filesystem — though /tmp is virtually always on the right sort of FS so it's probably not that — but it's still not recommended.)
- Is the development code really trying to write to that database, or is something “clever” catching you out and causing it to try to open something else? (I've been caught out by this in my code in the past; don't think it can't happen to you…)
- Are you using the same version of the SQLite library in the unit tests and the production code?
If you're not on the same machine, it's quite possible that the production system doesn't have a /tmp/cer directory. Obvious to fix that first. Similarly, if you're on the same machine but running as different users, you're likely to have permissions/ownership problems. Disk space is another serious gotcha, but less likely. I don't think it's the last three, but they're worth checking if the more obvious deployment problems are sorted. If it's none of the above, you've hit an exotic problem and will have to report much more info (it might even be a bug in SQLite, but knowing the developers of it, I believe that to be quite unlikely).
в строке подключения я определил пароль как "mypassword" если я удалю этот пароль, все работает хорошо, но когда я использую предложение password, это дает мне ошибку в подключении.открыть() синтаксис
Я искал в сети и нашел какую-то проблему с версией, но я использую версию 3 только так, как я сказал в строке подключения я также пробовал удалить "version=3", но проблема остается той же.
Я делаю это в первый раз, каково решение этого?
когда вы указываете пароль в строке подключения, и база данных уже существует, SQLite предполагает, что база данных зашифрована и попытается расшифровать ее с помощью указанного пароля. Если вы еще не установили пароль в базе данных, это приведет к ошибке "файл зашифрован", потому что предоставленный пароль нельзя использовать для расшифровки незашифрованной базы данных.
вы можете либо удалить базу данных, и SQLite создаст новую зашифрованную базу данных, используя пароль в строка подключения. Или вы можете зашифровать существующую базу данных с помощью ChangePassword() способ:
ответ 2Toad в основном правильный, но я хотел добавить свой собственный, потому что есть некоторые разъяснения. Как сказал 2Toad, это правильно:
когда вы указываете пароль в строке подключения, и база данных уже существует, SQLite предполагает, что база данных зашифрована и попытается расшифровать ее с помощью указанного пароля. Если вы еще не установили пароль в базе данных, это приведет к ошибке" файл зашифрован", потому что предоставленный пароль не может использоваться для расшифруйте незашифрованную базу данных.
но эта ошибка также может произойти, если вы пытаетесь использовать conn.SetPassword("something") после того, как у вас уже был другой в строке подключения. Или если вы делаете conn.ChangePassword("somethingelse") , а еще Password=something в строке подключения.
есть несколько сценариев:
- к базе данных был применен пароль, и он находится в строке подключения.
- у вас есть пароль в строке подключения, но база данных не применен, или пароль в строке не соответствует БД.
- в базе данных никогда не было пароля, и вы хотите его изменить.
- в базе данных есть пароль, и вы хотите его изменить.
поэтому код 2Toad предоставлены для выполнения conn.ChangePassword("somethingelse") только наполовину правильно и не учитывает, где вы находитесь, что еще вы сделали, и что вы хотите делать в будущем. Если у вас есть существующий пароль, и вы хотите его изменить, это правильно, но вы также должны быть уверены, что строка подключения будет обновлена после этого, или последующие соединения не удастся с file is encrypted ошибка.
этот сценарий происходит, если вы пустой пароль с помощью conn.SetPassword("") а потом попробовать conn.ChangePassword("somethingelse") без предварительного подключения к базе данных без Password=something в строке подключения. Это Password=something должно быть удалено из строка подключения, потому что пароль был удален программно из БД, и БД попытается подключиться к нему. Если он не удаляется из строки подключения одновременно с программным удалением из БД, вы получите то же самое file is encrypted ошибка.
потому что я начал с того, что сделал conn.SetPassword("something") в самом начале, когда у меня не было пароля применяется (и я считаю, что это способ сделать это), я не могу проверить без создание другой БД SQLite, но я не верю, что вы можете вызвать conn.ChangePassword("something") если у вас никогда не было пароля в первую очередь. Вы должны сделать conn.SetPassword("something") для начального набора, а затем положить Password=something в строке подключения.
кстати я сделал смену пароля, где я сделал conn.ChangePassword("somethingelse") только после conn.SetPassword("") и очистив Password=something в строке подключения:
это сработало. Я полагаю, вы также можете не ясно это из строки подключения и просто сделать conn.ChangePassword("somethingelse") , а затем добавить Password=somethingelse в строку, после:
лично я храню пароль как зашифрованный в приложении (веб) .конфигурационный файл и вызовите его в переменную в моем приложении onload и динамически создайте из него строку подключения.
Читайте также: