Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Если возьмём 1С-Программиста, то ничего из него не сделаем
Механизм ORM использующийся в платформе был изначально написан для блокировочных СУБД. Чтобы добавит поддержку версионных БД был разработан собственный механизм блокировок, который используется сейчас по умолчанию для всех новых конфигураций.
Такие запросы генерируются, когда отключен собственный механизм блокировок, чтобы делать блокировку на уровне таблицы. Этот режим сделан как заглушка, чтобы обеспечить правильность работы приложения для старых конфигураций.
Я не участвую в разработке платформы, сами разработчики тоже об этом не распространяются, поэтому могу лишь предположить, что причина в унифицированном доступе к остаткам. То есть заблокировали записи с остатками, проверили их, изменили. С версионными СУБД все по-другому, сначала их нужно изменить, а затем проверить.
Если при списании остатка нужно использовать FIFO все еще сложнее. Кроме того собственный механизм блокировок оказался очень полезен даже для MS SQL Server, т.к. он очень любит эскалировать блокировки до таблицы даже для небольшого набора записей.
Я не могу сказать, какие запросы использует платформа, чтобы заблокировать всю таблицу в Postgre SQL. Главное что платформа это делает.
1) Начинаем транзакцию в режиме Serializable
2) Читаем остатки из таблицы остатков ||| начиная с этого момента другие транзакции их не изменят
3) Делаем расчеты
4) Записываем новые остатки и фиксируем транзакцию.
Я нигде не ошибся? Если не ошибся, то именно так всё в 1С работает с MS SQL и DB2.
А вот с PostgreSQL и Oracle так у них не получилось, что им помешало не знаю.
Скорее всего по какой-то причине не могли определить автоматически, какие именно записи нужно заблокировать. И они использовали Read Comitted на всю таблицу.
Ну, если верить их сайту, то вполне используют. И конструкции языка запросов типа «ДЛЯ ИЗМЕНЕНИЯ» это подтверждают.
Если исходить из того, что в нормально работающей системе большинство транзакций по списанию товара будут успешными, а также что именно списание по партиям — это одна специфическая задача, где результат зависит от прочитанных данных, по тем же деньгам — главное просто контроль остатка, то оптимальнее выглядит такая система:
1) Открываем транзакцию
2) Делаем расчеты
3) Записываем новые остатки и блокируем таблицу остатков
4) Проверяем, не ушли ли в минус, если не ушли — фиксируем транзакцию, иначе отменяем.
Плюс тут в том, что этап расчетов выполняется до блокировки каких-либо данных.
А механизм управляемых блокировок дает возможность разработчику определить, в какой момент что блокировать.
1) Открываем транзакцию
2) Читаем таблицу остатков
3) Делаем расчеты
4) Проверяем, не ушли ли в минус, если ушли откат транзакции
5) Записываем новые остатки и фиксируем транзакцию.
И после п.2 другие транзакции не смогут выполнить п.2 у себя, верно?
А тот вариант как раз дает возможность работать с данными в других транзакциях, вплоть до записи новых остатков.
Другое дело что на списании партий такой вариант не проходит, но на списании просто количества, без партий — отлично работает.
И тут достаточно уровня Read comitted с начала транзакции, а перед записью новых остатков установить Serializable, потом быстро проверить остаток и транзакцию зафиксировать/откатить.
Технически и тут можно. Вам просто надо транзакцию открывать на моменте проверки остатков. Но лучше так не делать.Тогда нельзя будет откатить изменения, не влияющие на остаток, которые записаны до открытия транзакции.
Не надо так делать. Давайте поясню. В случае если вы делаете read commited то к моменту serializable у вас данные остатков могут быть не корректны. И это зависит от реализации вычисления остатков. Если это просто поле в записи, то все будет ок. А вот если у вас это вычисляемое значение по нескольким записям, то вы получите фантомное чтение, когда не будет учтен добавленный в соседней транзакции остаток.
Тогда нельзя будет откатить изменения, не влияющие на остаток, которые записаны до открытия транзакции.
Вот если повысить уровень изоляции — то да, сработает. Но не в курсе, возможно ли такое.
Для вычисляемых полей в 1С как раз и ставят при новом механизме блокировку, вручную, на те поля, которые влияют на остаток. Но в последних конфигурациях количество таких мест сведено к минимуму, а в основном используется подход, описанный мной. И остатки там «просто поле в записи», точнее в нескольких записях в одной таблице, и этот подход позволяет повысить параллельность работы пользователей.
Вобщем, мой вывод такой, что, реализовать всё можно. Но поведение в разных СУБД будет несколько отличаться, и 1С решили что проще сделать новый велосипед механизм, чем учитывать эти различия.
Возможность разработки… на русском и английском языках
// Изменения Антона
...
// Конец изменений Антона
Одним из заблуждений является то, что хороший программист 1С должен знать бухгалтерию.
Почему 1С — это хорошо