При работе с высоконагруженными системами на базе 1С:Предприятие критически важным параметром является режим управления блокировками. Флаг is_read_committed_snapshot_on (или RCSI) определяет, будет ли MS SQL Server использовать версионность строк для обеспечения согласованности чтений. Начиная с версии 8.3, этот режим является рекомендуемым для 1С, так как он значительно снижает количество взаимных блокировок (deadlocks) и ожиданий на таблицах.
Иногда возникает задача проверить состояние этого флага не в текущей базе, а на удаленном сервере или во вспомогательной базе данных. Рассмотрим подробнее, почему этот флаг может "слетать" и какими способами мы можем программно получить его значение из кода 1С.
Разберем ситуацию: после обновления конфигурации или миграции данных пользователи начинают жаловаться на участившиеся блокировки. Часто выясняется, что флаг is_read_committed_snapshot_on установлен в значение 0 (выключен). Проанализируем причины, по которым это происходит:
.dt, настройки SQL-базы берутся из системной базы model. Если в model версионность выключена, она будет выключена и в новой базе.Это классический и наиболее гибкий способ. Мы создаем соединение напрямую с SQL-сервером, минуя механизмы 1С. Это позволяет выполнить произвольный запрос к системным представлениям sys.databases.
Рассмотрим пример кода для получения статуса флага:
// Определим параметры подключения
СерверSQL = "SQL-SERVER-02";
ИмяБазы = "Trade_Production";
Логин = "sa";
Пароль = "StrongPassword123";
// Создаем объект соединения
Connection = Новый COMОбъект("ADODB.Connection");
ConnectionString = "Provider=SQLOLEDB;Data Source=" + СерверSQL + ";Initial Catalog=master;User ID=" + Логин + ";Password=" + Пароль + ";";
Попытка
Connection.Open(ConnectionString);
// Формируем текст запроса
ТекстЗапроса = "SELECT is_read_committed_snapshot_on FROM sys.databases WHERE name = '" + ИмяБазы + "'";
// Выполняем запрос
RecordSet = Connection.Execute(ТекстЗапроса);
Если Не RecordSet.EOF Тогда
ЗначениеФлага = RecordSet.Fields("is_read_committed_snapshot_on").Value;
Сообщить("Статус RCSI для базы " + ИмяБазы + ": " + ?(ЗначениеФлага = 1, "ВКЛЮЧЕН", "ВЫКЛЮЧЕН"));
КонецЕсли;
RecordSet.Close();
Connection.Close();
Исключение
Сообщить("Ошибка подключения к SQL: " + ОписаниеОшибки());
КонецПопытки;
Преимущества: не требует настройки метаданных в конфигурации, работает быстро.
Недостатки: необходимо хранить учетные данные SQL в коде или константах, требуется наличие провайдера SQLOLEDB на сервере 1С.
Если нам нужно часто обращаться к удаленному серверу, мы можем настроить так называемый Linked Server на стороне самого MS SQL Server. Это позволит нам писать запросы к удаленной базе так, как будто она находится на нашем локальном сервере.
Проанализируем шаги реализации:
ExternalDataSource (Внешний источник данных) или обычный запрос через ADODB к локальной базе, но с обращением к удаленной через четырехкомпонентное имя.Пример SQL-запроса через Linked Server:
SELECT is_read_committed_snapshot_on
FROM [REMOTE-SQL-SERVER].master.sys.databases
WHERE name = 'Remote_DB_Name'
Этот способ позволяет избежать передачи паролей внутри кода 1С, так как авторизация настраивается на уровне SQL Server.
Посмотрим на штатный механизм платформы 8.3. Мы можем добавить в конфигурацию ВнешнийИсточникДанных, подключиться к базе master удаленного сервера и выбрать таблицу (или представление) sys.databases.
После настройки объекта в конфигураторе, получение данных в коде будет выглядеть максимально просто:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| SQL_Databases.is_read_committed_snapshot_on
|ИЗ
| ВнешнийИсточникДанных.УдаленныйСервер.Таблица.sys_databases КАК SQL_Databases
|ГДЕ
| SQL_Databases.name = &ИмяБД";
Запрос.УстановитьПараметр("ИмяБД", "НашаБазаДанных");
Результат = Запрос.Выполнить();
// Далее обработка результата...
Важный нюанс: для доступа к системным таблицам через внешний источник данных может потребоваться создание специального View (представления) на стороне SQL, так как 1С не всегда корректно отображает системные объекты sys напрямую.
Выясним причину, по которой просто "включить" флаг программно из 1С бывает сложно. Для изменения режима READ_COMMITTED_SNAPSHOT требуется монопольный доступ к базе данных.
Команда SQL выглядит так:
ALTER DATABASE [ИмяБазы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяБазы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяБазы] SET MULTI_USER;
Внимание: выполнение этой команды из кода 1С приведет к немедленному разрыву всех соединений, включая ваше собственное. Поэтому в 1С рекомендуется только проверять статус флага, а уведомление об отклонении отправлять администратору базы данных для ручного исправления в период регламентного обслуживания.
Для предотвращения проблем с блокировками, создадим небольшую подсистему контроля. Она может работать как регламентное задание:
is_read_committed_snapshot_on.Такой подход позволяет оперативно реагировать на "слетевшие" настройки после плановых работ, не дожидаясь массовых жалоб пользователей на производительность системы.