1с не удалось зафиксировать таблицу для чтения users

Обновлено: 06.07.2024

Доступ к файловой системе из кода конфигурации

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

1. При обращении из кода конфигурации к файлам и каталогам файловой системы следует иметь в виду, что доступ к ним ограничен правами пользователя операционной системы, от имени которого запущено приложение.

1.1. Если доступ к файловой системе осуществляется из кода, выполняемого на клиенте, то он выполняется под правами пользователя, от имени которого запущено приложение (тонкий, толстый или веб-клиент). Как правило, это текущий пользователь операционной системы.

1.2. Если доступ к файловой системе осуществляется из кода, выполняемого на сервере, то:

  • при использовании клиент-серверной информационной базы, доступ ограничен правами пользователя, от имени которого запущен сервер 1С:Предприятия (*);
  • при использовании файловой базы, опубликованной на веб-сервере, доступ ограничен правами пользователя, от имени которого запущен веб-сервер.

* Рабочие процессы могут быть также запущены от имени другого пользователя, отличного от того, под которым запускается агент сервера. Подробнее см. руководство администратора клиент-серверного варианта, описание служебного файла swpuser.ini

Область применения (уточнение): управляемое приложение, обычное приложение.

2. Запрещается выполнять запись каких-либо файлов в каталог исполняемых файлов 1С:Предприятия, получаемого с помощью метода КаталогПрограммы . Использование метода КаталогПрограммы допустимо только для чтения или запуска файлов. Например, при работе в ОС Windows, для запуска копии тонкого клиента 1С:Предприятия текущей версии, допустимо использовать:

3. Даже если не планируется локализация конфигурации на другие языки, следует обеспечивать переносимость файлов, сформированных из кода конфигурации, между различными операционными системами с различными кодировками. Для этого необходимо:

3.1. В именах файлов, автоматически формируемых из кода конфигурации, указывать только английские буквы, а также цифры, а в качестве кодировки текстовых файлов использовать только UTF-8 (именно этот формат предпочтителен, т.к. только с ним корректно работает операционная система macOS).

3.2. В тех случаях, когда имя файла не генерируется системой, а его явно вводит пользователь, разрешить ввод русскоязычных имен, но при этом дать возможность транслитерировать его в англоязычное имя. По умолчанию, если это технически возможно и не снижает удобство работы, рекомендуется предлагать англоязычное имя файла, а для текстовых файлов – сохранение в кодировке UTF-8.

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

В конфигурациях на базе Библиотеки стандартных подсистем для транслитерации имен файлов рекомендуется использовать функцию СтроковыеФункцииКлиентСервер.СтрокаЛатиницей .

Работа с временными файлами и каталогами

При необходимости использования временных файлов и каталогов необходимо соблюдать следующие требования:

1. Для получения имени временного файла следует использовать метод ПолучитьИмяВременногоФайла (исключение составляет веб-клиент, см. ниже п. 3). В противном случае возможна некорректная работа конфигурации в многопользовательском режиме, с включенными профилями безопасностями, возникновение проблем с правами доступа к файлам операционной системы, а также неконтролируемое увеличение количества ненужных временных файлов, которые не будут своевременно удалены.

ИмяПромежуточногоФайла = "C:\Временные файлы 1С\TempFile.xml";
Данные.Записать(ИмяПромежуточногоФайла);

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

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

Кроме того, при использовании метода ПолучитьИмяВременногоФайла платформа 1С:Предприятие сохраняет контроль над такими файлами и автоматически удаляет их

  • при перезапуске рабочего процесса (если файл был создан на стороне сервера) или клиентского приложения (если файл был создан на стороне клиента);
  • через 20 минут после серверного вызова или сеанса, в котором создан временный файл (при работе в клиент-серверном варианте на платформе 8.3.17 и больше).

Если же имя временного файла было сформировано каким-то другим способом, и прикладной код не удалил (либо по какой-то причине не смог удалить) ранее созданный временный файл, то платформа такой файл не контролирует, и он остается в файловой системе на неопределенное время. Накапливание «потерянных» временных файлов может представлять серьезную проблему, особенно для информационных баз с большим количеством активно работающих пользователей (например, при работе в режиме сервиса).

Таким образом, неправильно :

Каталог = КаталогВременныхФайлов();
ИмяФайла = Строка(Новый УникальныйИдентификатор) + ".xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);

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

При использовании метода ПолучитьИмяВременногоФайла будет получено уникальное имя, гарантирован доступ к файлу, а также временный файл будет автоматически удален платформой 1С:Предприятие после завершения рабочего процесса сервера или клиентского приложения.

2. Для создания временного каталога рекомендуется также использовать имя, полученное при помощи метода ПолучитьИмяВременногоФайла (исключение составляет веб-клиент, см. ниже п. 3). Это гарантирует уникальность имени создаваемого каталога при работе в многопользовательском режиме и гарантирует, что после перезапуска рабочего процесса или клиентского приложения временный каталог будет автоматически удален платформой 1С:Предприятие. После этого, внутри созданного каталога можно создавать другие каталоги и файлы без ограничений.

3.1. При выполнении кода веб-клиентом метод ПолучитьИмяВременногоФайла недоступен. Поэтому для формирования имен временных файлов и каталогов необходимо использовать функцию КаталогВременныхФайлов и объект УникальныйИдентификатор .

Каталог = КаталогВременныхФайлов();
ИмяФайла = "TempDataFile.xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);

Каталог = КаталогВременныхФайлов();
ИмяФайла = Строка(Новый УникальныйИдентификатор) + ".xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);

3.2. Если в конфигурацию встроена Библиотека стандартных подсистем , для создания временных каталогов на стороне клиента необходимо использовать процедуру ФайловаяСистемаКлиент.СоздатьВременныйКаталог .

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

// Работа с файлом
.

// Удаляем временный файл
Попытка
УдалитьФайлы(ИмяПромежуточногоФайла);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Мой механизм.Действие'"), УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

5. При использовании временных файлов и каталогов на сервере, необходимо полностью завершать работу с ними в рамках одного серверного вызова. При работе конфигурации с использованием кластера серверов, при следующем вызове эти файлы могут стать недоступны, так как код начнет исполняться на другом компьютере. При необходимости сохранить данные между серверными вызовами в пределах одного сеанса следует использовать временное хранилище платформы (методы ПоместитьВоВременноеХранилище , ПолучитьИзВременногоХранилища ).

5.1. В редких случаях может возникнуть необходимость передачи данных во временных файлах между сеансами, например, при подготовке данных для фонового задания, при организации длительного процесса, обслуживающего несколько последовательных вызовов web-сервиса. Необходимо самостоятельно обеспечивать гарантировано общее место хранения, права для доступа к файлам из разных мест их обработки, удаление файлов по истечению сроков их обработки или аварийного завершения процесса обработки. Рекомендуется использовать следующий подход:

  • Для обеспечения доступа со всех возможных мест обработки заводится константа для хранения общего пути к файлам, доступного для доступа со всех серверов кластера;
  • При создании временных файлов их имена заносятся во вспомогательный регистр сведений с сохранением времени создания файла;
  • При штатном прохождении процесса, последняя операция, которой были нужны файлы, перед своим завершением удаляет как сам файл, так и записи о них во вспомогательном регистре;
  • Вспомогательное регламентное задание периодически проверяет наличие записей во вспомогательном регистре, время существования которых заведомо превышает время штатного завершения процесса. При обнаружении таких записей, задание удаляет временные файлы и записи о них.

Передача файлов между клиентом и сервером

1. При одновременной работе с файлом на клиенте и на сервере необходимо использовать передачу файла через временное хранилище (методы ПоместитьФайлы , ПолучитьФайл , ПолучитьФайлы , НачатьПомещениеФайла , ПоместитьВоВременноеХранилище , ПолучитьИзВременногоХранилища ). В общем случае клиент и серверы кластера - это разные компьютеры с разной файловой системой, причем доступ к файлам может происходить под разными пользователями ОС с различными правами.

&НаКлиенте
Процедура ОбработатьФайл()
.
ИмяФайла = "C:\Файлы для обработки\Загрузка.xml";
Результат = ПроизвестиОбработкуНаСервере(ИмяФайла);
.

Чтение = Новый ЧтениеТекста(ИмяФайла);
.

Результат = Чтение.Прочитать();
Возврат Результат;

ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
ОписаниеОповещения = Новый ОписаниеОповещения(
"ОбработатьФайлЗавершение", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения,,
ИмяФайлаДляОбработки, Ложь,
УникальныйИдентификатор);

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)

Данные = ПолучитьИзВременногоХранилища(Адрес);
ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("txt");
Данные.Записать(ИмяПромежуточногоФайла);

Чтение = Новый ЧтениеТекста(ИмяПромежуточногоФайла);
.
Результат = Чтение.Прочитать();
.

2. Для сохранения данных во временном хранилище между несколькими серверными вызовами, при помещении его в хранилище необходимо использовать параметр УникальныйИдентификаторФормы метода ПоместитьФайл , передав в него идентификатор текущей формы. Такие значения будут удалены из временного хранилища только при закрытии указанной формы. При этом, при повторном помещении того же файла во временное хранилище, предыдущее значение необходимо удалять вручную. Например:

.
// Первый серверный вызов
ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
ОписаниеОповещения = Новый ОписаниеОповещения(
"ОбработатьФайлЗавершение", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения,,
ИмяФайлаДляОбработки, Ложь,
УникальныйИдентификатор);

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)

.
Результат = ПроизвестиНачальнуюОбработкуНаСервере(Адрес);
ПродолжитьОбработкуФайла();
.

.
// Второй серверный вызов с той же версией файла
Результат = ПроизвестиПромежуточнуюОбработкуНаСервере(Адрес);
.

// Третий серверный вызов с новой версией файла
ОписаниеОповещения = Новый ОписаниеОповещения(
"ПродолжитьОбработкуФайлаЗавершение", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения,,
ИмяФайлаДляОбработки, Ложь,
УникальныйИдентификатор);

Процедура ПродолжитьОбработкуФайлаЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)

При этом во временном хранилище формы останется две копии файлов. Адрес второй копии будет находиться в переменной Адрес , а адрес первой копии будет утерян. Это приводит к затрате дополнительных ресурсов приложения, замедлению работы.

.
// Первый серверный вызов
ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";

ОписаниеОповещения = Новый ОписаниеОповещения(
"ОбработатьФайлЗавершение", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения,,
ИмяФайлаДляОбработки, Ложь,
УникальныйИдентификатор);
.

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)

.
Результат = ПроизвестиНачальнуюОбработкуНаСервере(Адрес);
ПродолжитьОбработкуФайла();
.

.
// Второй серверный вызов с той же версией файла
Результат = ПроизвестиПромежуточнуюОбработкуНаСервере(Адрес);
.

// Третий серверный вызов с новой версией файла
УдалитьИзВременногоХранилища(Адрес);

ОписаниеОповещения = Новый ОписаниеОповещения(
"ПродолжитьОбработкуФайлаЗавершение", ЭтотОбъект);

НачатьПомещениеФайла(ОписаниеОповещения,,
ИмяФайлаДляОбработки, Ложь,
УникальныйИдентификатор);

&НаКлиенте
Процедура ПродолжитьОбработкуФайлаЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)

3. Если в конфигурацию встроена Библиотека стандартных подсистем для помещения файлов во временное хранилище необходимо использовать процедуры ЗагрузитьФайл и ЗагрузитьФайлы общего модуля ФайловаяСистемаКлиент . Для сохранения данных файла между несколькими серверными вызовами необходимо использовать свойство ИдентификаторФормы параметра ПараметрыЗагрузки :

&НаКлиенте
Процедура ОбработатьФайл()
.
ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьФайлЗавершение", ЭтотОбъект);

ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
ПараметрыЗагрузки.Интерактивно = Ложь;

ФайловаяСистемаКлиент.ЗагрузитьФайл(ОписаниеОповещения,
ПараметрыЗагрузки, ИмяФайлаДляОбработки);

&НаКлиенте
Процедура ОбработатьФайлЗавершение(ПомещенныйФайл, ДополнительныеПараметры)

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

Речь пойдет о файловом варианте работы с хранилищем.

1. Ошибка аутентификации в хранилище конфигурации


Самая понятная из возможных ошибок. Данная ошибка возникает при вводе неверного логина и пароля.

Изменить логин и пароль может пользователь с административными правами на вкладке "Пользователи" окна "Администрирование хранилища конфигурации"

2. Пользователь существующей связи отличается от текущего


Тут важно понимать принцип работы хранилища конфигурации. Хранилище используются для коллективной разработки, т.е. у каждого разработчика есть своя база для разработки, есть свой пользователь хранилища, и все под своими логинами подключаются в свои базы. На практике бывает, что существуют общие базы, например на сервере для тестирования, и если она подключается к хранилищу, для нее необходимо заводить также отдельный логин и заходить в нее под ним (для удобства, в качество логина общей серверной базы можно использовать имя самой базы). Девиз хранилища: на каждую базу свой логин в хранилище.

Данная ошибка возникает, когда текущая база уже подключена к хранилищу под каким-то логином, а вы пытаетесь ввести другой логин. Это может быть по разным причинам:

  • вы зашли в общую базу и пытаетесь войти под своим логином хранилища. Необходимо выяснить логин этой конкретной базы, и заходить под ним, но не переподключать под своим. Посмотреть, под каким логином подключена каждая база может пользователь с административными правами в хранилище, на вкладке "Подключения" окна "Администрирование хранилища конфигурации"
  • вы развернули базу, которая уже была подключена к хранилищу. Необходимо отключить конфигурацию от хранилища и подключить заново.

3. Пользователь уже аутентифицирован в хранилище


Данная ошибка возникает, когда любая другая база уже подключена к хранилищу под логином, который вы вводите в текущей базе. И с ней работают под этим логином в данный момент.

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

4. Для данного пользователя уже имеется конфигурация связанная с данным хранилищем конфигурации


Предупреждение похоже на ошибку из предыдущего пункта, но есть небольшое отличие.

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

Предупреждение позволяет подключиться под введенным логином, но нужно понимать последствия. Если вы подключитесь под эти логином, то у другого пользователя рано или поздно возникнет ошибка из предыдущего пункта или аналогичное предупреждение. Рекомендую подключиться в хранилище под другим логином, либо найти того, кто подключился в другой базе под этим логином и договориться о том, кто использует этот логин.

5. При получении данных из хранилища или захвате объекта: Не удалось зафиксировать таблицу для чтения "Versions"


Данная ошибка возникает, когда вы уже длительное время подключены к хранилищу и за период работы были разрывы соединения.

Чтобы избавиться от ошибки, необходимо закрыть конфигуратор и зайти заново.

6. При подключении к хранилищу: Не удалось зафиксировать таблицу для чтения "Users"

Данная ошибка может возникать:

  • когда вы уже длительное время подключены к хранилищу и за период работы были разрывы соединения.

Чтобы избавиться от ошибки, необходимо закрыть конфигуратор и зайти заново.

  • когда в этот самый момент другой пользователь помещает большой объем данных в хранилище

Необходимо подождать, пока другой пользователь закончит помещение объектов в хранилище.

7. Файл не является файлом базы данных

Ошибка соединения с хранилищем конфигурации по адресу:
\\Server\Repository\project1
по причине:
Файл не является файлом базы данных '//Server/Repository/project1/1cv8ddb.1CD'

Данная ошибка может возникать при подключении к хранилищу:

  • если есть зависший фоновый процесс к этой базе.

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


  • если есть зависший сеанс другой базы, подключенной к этому хранилищу на этом компьютере

Так бывает, что одновременно приходится работать с разными базами в одном хранилище. Если про одну базу надолго забыть, и в ней будет появляться ошибка №5, то другую базу с этим хранилищем вы открыть не сможете. Необходимо завершить "забытые" сеансы.

8. Файл базы данных поврежден.

Ошибка соединения с хранилищем конфигурации по адресу:
\\Server\Repository\project1
по причине:
Файл базы данных поврежден '\\Server\Repository\project1\//1cv8ddb.1CD'

Данная ошибка может возникать:

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

1. Всем разработчикам закрыть все конфигураторы, подключенные к хранилищу

2. Почистить кэш хранилища

3. Одному запустить конфигуратор от имени администратора

4. Подключиться к хранилищу

Если указанные действия не помогли, можно воспользоваться утилитой chdbfl.exe, но в моей памяти мне она ни разу не помогла и единственным выходом было создание хранилища с нуля.

9. Неклассифицированная ошибка работы с хранилищем конфигурации


Данная ошибка может возникать, когда к хранилищу подключаются разными версиями платформы. Например: 8.3.10.2667 и 8.3.12.1529

1. Всем разработчикам закрыть все конфигураторы, подключенные к хранилищу

2. Очистить глобальный кэш хранилища

3. Синхронизировать версии платформ.

10. Ошибка "База данных не открыта"


Данная ошибка может возникать при подключении к хранилищу:

  • если есть зависший фоновый процесс к этой базе;
  • если есть зависшие блокировочные файлы в каталоге хранилища.

1. Если причина в зависших фоновых процессах на локальном компьютере, то лечение как в п.7.

2. Если п.7 не помог, то необходимо всем закрыть конфигураторы, зайти в каталог хранилища, и удалить блокировочные файлы размером 0 байт.

11. Ошибка "Ошибка совместного доступа к хранилищу конфигурации"

При получении данных из хранилища возникает ошибка:

---- Начало операции с хранилищем конфигурации ----
Повтор попытки получения объектов из хранилища конфигурации
Повтор попытки получения объектов из хранилища конфигурации
Повтор попытки получения объектов из хранилища конфигурации
Повтор попытки получения объектов из хранилища конфигурации
Повтор попытки получения объектов из хранилища конфигурации
Повтор попытки получения объектов из хранилища конфигурации
Ошибка совместного доступа к хранилищу конфигурации:

\\Server\Repository\project1
Не удалось заблокировать таблицу 'OBJECTS'
---- Операция с хранилищем конфигурации отменена ----

Данная ошибка может возникать при получении данных из хранилища:

  • если в этот момент с другого компьютера запущен процесс оптимизации хранилища;

1. Дождаться окончания оптимизации хранилища

2. Повторно запросить получение данных из хранилища.

Это, конечно, не весь список ошибок, который может возникать при работе с хранилищем. Я привёл те ошибки, с которыми я лично не раз сталкивался и решал указанными мной способами. Если у вас есть ошибка, которая не описана, и вы знаете способ ее решения, пишите в комментарий, я с удовольствием добавлю информацию в общую статью.

Некоторые особенности устройства и работы файловой базы данных «1С:Предприятия 8»

В данном разделе рассматриваются некоторые особенности внутреннего устройства и работы механизмов файловой базы данных «1С:Предприятия 8», которые не освещены в документации, но могут быть интересны пользователям и разработчикам прикладных решений на платформе «1С:Предприятие 8». Приведенное описание соответствует платформе «1С:Предприятие» версии 8.3.4.

Устройство файла *.1CD

На самом нижнем уровне файл *.1CD или файл базы данных содержит внутри своего рода файловую систему, включающую в себя так называемые внутренние файлы. Файл *.1CD имеет страничную организацию, то есть состоит из страниц размером 4096 байт (4 К). Размер файла *.1CD всегда кратен 4 К.

Каждая из остальных страниц может либо принадлежать какому-либо из внутренних файлов, либо находиться в списке свободных страниц.

Внутренние файлы

  • корневая страница,
  • индексные страницы,
  • страницы данных.

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

Корневая страница содержит служебную информацию внутреннего файла, такую как длина файла, номер версии данных файла и т. п. Кроме того, на корневой странице содержится до 1018 номеров индексных страниц.

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

Из сказанного выше следует, что внутренний файл может включать не более чем 1 041 414 (1018 * 1023) страниц данных. Следовательно, максимальный размер внутреннего файла не может превышать 4 265 631 744 (1018 * 1023 * 4096) байта. Для адресации отдельных байтов внутреннего файла используются 4-байтовые целые числа без знака.

Для представления внутреннего файла нулевой длины достаточно одной только корневой страницы. Если размер внутреннего файла составляет от 1 до 4096, то он представляется тремя страницами: одной корневой, одной индексной и одной страницей данных. При дальнейшем росте размера файла добавляются новые страницы данных, и их номера помещаются в индексную страницу. Как только индексная страница перестает вмещать номера страниц данных, добавляется новая индексная страница и ее номер добавляется в корневую страницу. И так далее.

Внутренние файлы не имеют имен. Для идентификации внутренних файлов используются номера их корневых страниц.

Список свободных страниц

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

Устройство базы данных

Внутренние файлы в конечном счете предназначены для хранения базы данных. База данных представляет собой совокупность таблиц. Каждой таблице может соответствовать от двух до четырех внутренних файлов:

  • файл описания таблицы,
  • файл данных,
  • файл индексов,
  • файл данных неограниченной длины.

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

Кроме того, имеется файл описания базы данных. Данный файл содержит информацию о локали базы данных, а также номера корневых страниц внутренних файлов описания для каждой из таблиц базы данных.

Таблицы

Файл описания таблицы

Файл описания таблицы содержит полное описание таблицы, которое включает:

  • имя таблицы;
  • перечень колонок таблицы, включая их имена и типы;
  • перечень индексов таблицы, включая их имена и индексируемые колонки;
  • номера корневых страниц внутренних файлов данных, индексов и данных неограниченной длины.

При открытии базы данных считывается файл описания базы данных и адресуемые им файлы описания таблиц. На основании этой информации инициализируются внутренние структуры данных, необходимые во время выполнения. Прочие файлы таблиц на этом этапе не открываются. Их открытие выполняется по мере обращения к таблицам. Это сделано из соображения ускорения процесса открытия, а также из предположения, что в данном сеансе могут быть обращения не ко всем таблицам базы данных.

Файл данных

Файл данных содержит записи таблицы. Каждая запись содержит значения всех колонок таблицы, кроме значений колонок неограниченной длины. Записи имеют фиксированную длину. Поэтому адрес записи может быть легко вычислен по номеру записи (N) и длине (L) как N * L .

Номера записи представлены 4-байтовыми целыми числами. Запись с номером 0 используется для служебных целей. Номера «настоящих» записей начинаются с 1.

Длина записи может быть вычислена как сумма длин всех колонок плюс от 1 до 17 байт служебной информации. Ограничений на длину записи не накладывается.

Ниже приведена информация о типах данных и соответствующем размере колонок:

Десятичное число с фиксированной точкой. Хранится в десятичном виде по две десятичные цифры на один байт. Зарезервировано место для знака. Размер может быть вычислен по формуле:

(p + 1) / 2 + ( p + 1) % 2

Строка фиксированной длины, состоящая из n однобайтовых символов. Размер колонки равен n .

Строка Unicode фиксированной длины, состоящая из n символов в кодировке UTF-16. Размер колонки равен n * 2 .

Двоичные данные фиксированной длины. Размер колонки равен n .

Строка переменной длины, состоящая не более чем из n однобайтовых символов. Размер колонки равен n + 2 байта. Дополнительные 2 байта используются для хранения фактической длины.

Строка Unicode переменной длины, состоящая не более чем из n символов в кодировке UTF-16. Размер колонки равен n * 2 + 2 . Дополнительные 2 байта используются для хранения фактической длины.

Двоичные данные переменной длины не более n байт. Размер колонки равен n + 2 байта. Дополнительные 2 байта используются для хранения фактической длины.

Значение логического типа (true или false). Размер колонки равен одному байту.

Дата без времени. Размер колонки – 4 байта.

Дата и время. Размер колонки – 7 байт.

Текст неограниченной длины, состоящий из однобайтовых символов. В структуре записи колонка занимает два 4-байтовых целых числа: фактическая длина значения и адрес в файле данных неограниченной длины. Фактические значения хранятся в файле данных неограниченной длины.

Текст Unicode неограниченной длины, состоящий из символов в кодировке UTF-16. В структуре записи колонка занимает два 4-байтовых целых числа: фактическая длина значения и адрес в файле данных неограниченной длины. Фактические значения хранятся в файле данных неограниченной длины.

Двоичные данные неограниченной длины. В структуре записи колонка занимает два 4-байтовых целых числа: фактическая длина значения и адрес в файле данных неограниченной длины. Фактические значения хранятся в файле данных неограниченной длины.

Кроме того, к размеру колонок, которые могут содержать NULL, добавляется еще один байт.

Файл индексов

В файле индексов находятся все индексы, определенные для таблицы. Детальное рассмотрение структуры индексов не входит в цели данной статьи. Отметим только, что индекс представляет собой сбалансированное дерево. С точки зрения использования файловой базы данных важным является то, что, в отличие от размера записи, на длину ключа индекса наложено ограничение: длина не может превышать 1920 байт. Ключ представляет собой конкатенацию значений всех индексируемых колонок записи плюс 4-байтовый номер записи.

Индексироваться могут колонки типов Numeric, Char, NChar, Binary, VarChar, NVarChar, VarBinary, Logical, Date и DateTime. Значение каждой из индексируемых колонок типов Numeric, Binary, VarBinary, Logical, Date и DateTime помещается в ключ как есть. Соответственно, каждая из таких колонок добавляет к длине ключа свой собственный размер. А вот для колонок типов Char, NChar, VarChar и NVarChar вместо самой строки в ключ помещается ее ключ сортировки (collation key). Поэтому вклад колонок указанных типов в длину ключа определяется как n * 3 + 2 для колонок, не чувствительных к регистру букв. И n * 4 + 3 для колонок, чувствительных к регистру.

Файл данных неограниченной длины

В файле данных неограниченной длины хранятся фактические значения колонок типов Text, NText и Image. Для хранения таких значений файл организован как набор блоков длиной 256 байт. Каждое значение хранится как односвязный список блоков. В каждом блоке содержатся:

  • адрес следующего блока (4 байта);
  • число используемых байт данных в данном блоке (2 байта);
  • полезные данные (250 байт).

Блок с адресом 0 используется для служебных нужд, а если точнее он содержит адрес списка свободных блоков. В список свободных блоков помещаются освободившиеся блоки, которые могут быть использованы в дальнейшем.

Работа с базой данных

Чтение данных

Следует различать чтение данных, выполняемое вне транзакции, и чтение в рамках транзакции. Операция чтения (например, SQL-запрос SELECT), выполняемая вне транзакции, получает данные, соответствующие состоянию базы данных на момент выполнения операции. При использовании SELECT вне транзакции поведение файловой базы данных подобно поведению версионных СУБД, таких как Oracle. То есть все данные, полученные запросом SELECT, относятся к одному согласованному состоянию базы данных, имевшему место на начало выполнения операции. Чтение данных не может быть заблокировано никакой другой операцией чтения или записи. Но нужно понимать, что состояние, имевшее место на начало чтения, может быть изменено. Соответственно, считываемые данные могут оказаться устаревшими.

Если чтение выполняется в рамках транзакции, то гарантируется, что считанные данные не могут быть изменены никем другим до завершения транзакции. Для обеспечения этой неизменности используется механизм транзакционных блокировок. При первом обращении к таблице на чтение в рамках транзакции на таблицу накладывается Read-блокировка. И эта блокировка не снимается до завершения транзакции.

Запись данных

Запись данных всегда предполагает наличие транзакции. Если операция записи была вызвана вне объемлющей транзакции, то транзакция будет создана неявно в процессе выполнения операции. При выполнении операции записи на таблицы, в которые вносятся изменения, накладывается транзакционная Write-блокировка, препятствующая чтению или записи, выполняемой другими соединениями.

Если на таблицу уже была наложена Read-блокировка, то выполняется ее эскалация до Write-блокировки.

Операции записи данных, выполняемые в рамках транзакции, не приводят к немедленной записи изменений в файл *.1CD. Изменения, вызванные операциями записи, накапливаются в кеше модифицированных страниц и сбрасываются в файл базы данных при фиксации (commit) транзакции.

Таким образом, если в процессе выполнения транзакции, до ее фиксации, произойдет сбой и/или падение приложения, то все изменения, произведенные в транзакции, окажутся потерянными и файл базы данных останется в неизмененном состоянии.

Кеширование данных

Кеш считанных страниц

Для повышения эффективности операций чтения механизмы файловой базы данных стараются кешировать считанные данные и тем самым минимизировать число физических операций чтения из файла базы данных. Кеш считанных страниц содержит прочитанные страницы данных внутренних файлов. Общий размер кеша для каждого из соединений с файловой базой данных является ограниченным и может в зависимости от различных условий составлять от 2 до 200 Мбайт. Кеш наибольшего размера создается при работе с файлом базы данных, расположенным на сетевом диске.

Кеш организован по принципу LRU. То есть страницы, к которым дольше всего не было обращений, могут быть вытеснены из кеша вновь считанными страницами.

Другой причиной, по которой страницы могут быть исключены из кеша, является его обновление. Каждое зафиксированное состояние данных внутреннего файла имеет соответствующий номер версии. Все кешируемые страницы внутреннего файла соответствуют определенной версии внутреннего файла. Процесс обновления состоит в том, что из файла базы данных считывается текущая версия внутреннего файла и сравнивается с версией кешируемых страниц. Если выясняется, что версия кешируемых страниц устарела, то страницы соответствующего внутреннего файла исключаются из кеша.

Для каждой операции чтения, выполняемой вне транзакции, обновление кеша производится для внутренних файлов данных, индексов и данных неограниченной длины каждой из таблиц, задействованных в операции чтения.

В рамках транзакции обновление кеша производится непосредственно после наложения на таблицу Read-блокировки. В дальнейшем до завершения транзакции кеш остается актуальным, так как таблица не может быть модифицирована другими транзакциями. Соответственно, для последующих операций чтения в той же транзакции обновления кеша не требуется.

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

Еще одной причиной для исключения страницы из кеша считанных страниц является попадание страницы в кеш модифицированных страниц.

Модификация данных и кеш модифицированных страниц

При запросе на чтение данных из внутреннего файла соответствующая страница сначала ищется в кеше модифицированных страниц. Если не найдена, то производится поиск в кеше считанных страниц. И если не найдена там, то производится считывание страницы из файла с помещением в кеш считанных страниц.

Сброс кеша модифицированных страниц в файл производится только при выполнении фиксации (commit) транзакции. При фиксации транзакции все измененные страницы всех внутренних файлов собираются в общий массив, упорядоченный по номерам страниц в файле базы данных, и запись в файл базы данных производится от больших номеров страниц к меньшим. Это делается из следующих соображений:

  • Если запись страницы с самым большим номером должна привести к увеличению файла базы данных, а на диске недостаточно места, то эта операция завершится аварийно. Таким образом, ни одно изменение не будет записано, транзакция будет отменена и файл *.1CD останется в неизмененном состоянии.
  • При записи от больших номеров страниц к меньшим статистически сначала будут записываться изменения в страницах данных, затем изменения в индексных страницах и только потом изменения в корневых страницах внутренних файлов. В результате минимизируется риск фатальных разрушений во внутренней структуре файла базы данных, если успешно завершится только часть операций записи.

Время жизни кеша модифицированных страниц ограничено временем выполнения транзакции. После завершения транзакции кеш полностью освобождается.

На размер кеша модифицированных страниц не накладывается никаких ограничений. Единственным ограничителем является размер свободной оперативной памяти.

Блокировки

Для обеспечения согласованности и целостности данных при разделенном режиме доступа к базе используются блокировки. Так как механика файловой базы данных работает в режиме файл-сервер, то есть отсутствует выделенный сервер баз данных, то блокировки в базе данных реализованы с использованием функций блокировки участков файла. Для блокировок используется файл с расширением .1CL.

Транзакционные блокировки

Этот вид блокировок уже упоминался выше. Транзакционные блокировки предназначены главным образом для обеспечения логической целостности и изоляции транзакций. Транзакционные блокировки бывают двух видов:

Read-блокировки не конфликтуют между собой, но конфликтуют с Write-блокировками. Write-блокировки конфликтуют с любыми блокировками: Read и Write. Единицей блокировки является таблица. Единица довольно крупная, особенно с учетом того, что в большинстве современных СУБД поддерживаются блокировки на уровне записи. Однако реализация блокировки на уровне записи потребовала бы большого числа файловых блокировок, что привело бы к существенному снижению производительности.

Транзакционные блокировки накладываются с ожиданием. По умолчанию время ожидания транзакционной блокировки равно 20 сек.

Блокировки фиксации состояния

Также имеется ряд блокировок фиксации состояния. Данный вид блокировок относится к системным блокировкам и предназначен для обеспечения согласованного доступа к файлу базы данных на физическом уровне. При использовании файловой базы данных крайне редко приходится сталкиваться с какими-либо внешними проявлениями, связанными с этим видом блокировок. В данной статье они упоминаются главным образом для полноты картины.

Поясним место этих блокировок на примере фиксации транзакции. Как было сказано выше, при фиксации результатов транзакции все изменения записываются в файл базы данных. Естественно, что пока процесс записи изменений не завершен, файл базы данных находится в рассогласованном состоянии. Соответственно, попытка чтения приведет к получению рассогласованных данных. Но записываемые данные относятся не ко всем таблицам, а только к измененным. Соответственно, нужно сделать так, чтобы никакие данные, имеющие отношение к модифицируемым таблицам, не считывались, пока запись изменений не завершена. Для обеспечения этого предусмотрена блокировка фиксации таблицы для записи и для чтения.

На время записи изменений, произведенных транзакцией, устанавливается фиксация для записи всех модифицированных транзакцией таблиц. А на время чтения данных, связанных с таблицей, устанавливается фиксация для чтения. Фиксация для записи конфликтует с фиксацией для чтения. Фиксации для чтения не конфликтуют между собой, но конфликтуют с фиксацией для записи. Соответственно, гарантируется, что, пока запись не завершена, никакие операции чтения не могут быть выполнены. А также, пока не завершено чтение, запись изменений не может быть начата.

Читайте также: