Продолжаю разгребать последние ошибки в логах OwnCloud. После многочисленных оптимизаций работы сервиса в логах осталось несколько постоянно встречающихся ошибок. Взялся разобраться с самой частой на данный момент:
Error while running background job (class: OCA\\Files_Sharing\\DeleteOrphanedSharesJob, arguments: ): {\"Exception\":\"Doctrine\\\\DBAL\\\\Exception\\\\LockWaitTimeoutException\",\"Message\":\"An exception occurred while executing 'DELETE FROM `oc_share` WHERE `item_type` in ('file', 'folder') AND NOT EXISTS (SELECT `fileid` FROM `oc_filecache` WHERE `file_source` = `fileid`)':\\n\\n SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
Специально сохранил синтаксис лога, но самое важное это:
- Ошибка при запуске фоновой задачи: DeleteOrphanedSharesJob.
- Ошибка в БД: LockWaitTimeoutException.
- Ошибка при обращении к таблицам:
oc_shareиoc_filecache. Фоновое задание DeleteOrphanedSharesJob не может выполнить DELETE-запрос к таблицеoc_share, потому что другие транзакции удерживают блокировки.
Начинаем анализировать. Понятно, что проблема связана с блокировкой таблиц в БД при запуске фоновых задач.

Я сделал выборку всех строк данной ошибки в логе, стало заметно, что ошибка повторяется каждые 30 минут. Вероятно, первый участник блокировки связан с задачами, которые выполняются по расписанию. В кроне у меня есть такая задача:
*/30 * * * * /usr/bin/php -f /var/www/owncloud/occ system:cronКаждые 30 минут запускается system:cron, и это совпадает с периодичностью ошибок блокировок БД. Рекомендуется это делать каждые 15 минут, но я увеличил интервал.
Фоновые задания OwnCloud (включая DeleteOrphanedSharesJob) запускаются через occ system:cron, и некоторые из них могут:
- Запускаться одновременно из-за наложения выполнения предыдущего и нового запуска.
- Конфликтовать друг с другом при работе с одними и теми же таблицами.
- Создавать длительные транзакции, которые не успевают завершиться за 30 минут.
Задача system:cron поддерживает параллельный запуск. Можно запустить несколько процессов и каждый из них получит свой набор данных для обработки. Так что здесь конфликтов быть не может, конфликт где-то ещё. На самом деле мне даже понятно где именно.
Ранее я настраивал синхронизацию файлов:
Синхронизация запускается каждый час в рабочее время:
0 7-19 * * * /opt/cron/owncloud_scan.sh 2>/var/log/owncloud/cron_errors.logИ это у нас первый кандидат на второй источник блокировок. Внутри скрипта выполняется files:scan. Он интенсивно работает с таблицей oc_filecache, что пересекается с запросом джоба.
Оба задания обращаются к одним и тем же таблицам (oc_share и oc_filecache). Возможна даже ситуация с взаимными блокировками. И действительно, в некоторых случаях в логе встречается ошибка Deadlock.
Решение простое, когда работает синхронизация файлов, не запускать задачу system:cron. А чтобы system:cron всё-таки работал, в рабочее время, нужно запускать его внутри скрипта owncloud_scan.sh. Собственно, так и сделал, пол дня прошло, — ошибок нет.
