В 2013 году я опубликовал пост "Транзакция SE14 : утилита базы данных", в которой описал основные моменты по использованию этой транзакции.
Как вы помните, в SAP системе существует два словаря:
Объект (таблица, индекс), созданный по всем правилам разработки в SAP системе, должен существовать в обоих словарях (рис 1).
Давайте спустимся в кроличью нору немного глубже. :)
Когда я рассказывал про SAP Program buffer на уровне сервера приложений SAP, я упоминал про ABAP loads, которые генерируются для каждой ABAP программы и запускаются ABAP процессором в рабочих процессах инстанции. Для таблиц ситуация похожая. Для каждого объекта ABAP Dictionary (таблицы/домена/структуры и т.п.) существует динамический объект (Runtime object), который генерируется на основе записи из SAP словаря, и содержит техническую информацию об объекте. ABAP программа работает с элементами ABAP словаря не напрямую, а через динамические объекты.
Динамический объект генерируется автоматически при активации (транзакция SE11: ABAP словарь) новой таблицы или внесении изменений в существующую. Динамический объект можно просмотреть, если в транзакции SE11 выбрать пункт меню "Утилиты -> Динамический объект -> Просмотреть" (рис. 2).
Динамические объекты, которые являются активными в текущий момент времени, отображаются в виде двух частей (рис. 3):
Таблицы, в которых хранятся активные динамические объекты, существуют только на уровне базы данных и их нет в ABAP Dictionary. Поэтому посмотреть их структуру можно только в транзакции SE14 или на уровне базы данных. А для просмотра содержимого можно воспользоваться функциональным модулем DD_SHOW_NAMETAB (транзакция SE37). При обновлении объектов через транспортные запросы используется аналогичная пара таблиц для временного хранения неактивных объектов ABAP словаря - DDXTT и DDXTF.
Для того, чтобы проверить корректность динамического объекта, то есть соответствие его активному объекту ABAP словаря, необходимо в SE11 или SE14 выбрать пункт меню "Утилиты -> Динамический объект -> Проверить" (рис. 2). Результатом проверки будет окно вида (рис. 4).
Вернемся обратно к основной теме.
Почему я всё это рассказал? А потому что объект в Database Dictionary создается на основе динамического объекта (Runtime object). То есть только для активного объекта ABAP словаря, который прошёл все проверки на уровне сервера приложений SAP. И, если мы хотим проверить объект базы данных, выбрав в SE11 пункт меню "Утилиты -> Объект базы данных -> Проверить" (рис. 5), то будет произведена сверка объекта из Database Dictionary и динамического объекта на уровне сервера приложений SAP.
Таким образом, можно отобразить взаимосвязь объектов следующим образом (рис. 6).
Иногда во всей этой отлаженной машине возникают коллизии. В основном, при изменении объектов ABAP словаря - перенос транспортных запросов, импорт пакетов обновлений и так далее.
Хочу рассказать историю, которая произошла у меня на проекте в канун последнего Нового Года. Разработчик расширил таблицу на одно поле в системе разработки. Так как тестовой системы временно не было (тут можно вспомнить о важности тестовой системы), было принято решение импортировать запрос с изменениями в продуктивную систему перед новогодними каникулами. При импорте запроса разработчик не учёл, что за время работы с данной функциональностью в системе, таблица выросла на 200 миллионов записей (как у классика: за время в пути собачка могла подрасти). В итоге, импорт запроса проходил успешно. Активация изменений в таблице на уровне ABAP словаря тоже выполнялась успешно. Изменённый динамический объект генерировался, а вот дальше происходил сбой. Таблица на уровне базы данных упрямо не хотела адаптировать изменения - добавлять новое поле.
Что же может помочь при решении проблем с объектами ABAP словаря?
Во-первых, два инструмента - транзакции SE11 и SE14, которые можно использовать для локализации проблемы. Необходимо проверить статусы объекта на уровне всех словарей: динамический объект, таблицу на уровне базы данных. Нет ли где несоответствий и ошибок. При работе системы с некорректным динамическим объектом возникают дампы вида DDIC_TYPE_INCONSISTENCY, DDIC_TYPELENG_INCONSISTENT, DDIC_TYPE_REF_ACCESS_ERROR, TYPELOAD_NEW_VERSION и т.п.
Во вторых, при проблемах на уровне базы данных: для создания отсутствующих объектов или активации изменений на уровне базы данных необходимо использовать транзакцию SE14 (первый пост про транзакцию SE14).
В-третьих, при коллизиях с динамическим объектом можно попробовать удалить его (то есть записи из таблиц DDNTT и DDNTF) через функциональный модуль DD_NAMETAB_DELETE (транзакция SE37). После этого динамический объект можно попробовать заново сгенерировать через активацию таблицы в транзакции SE11.
Ну и наконец, при проблемах с объектом базы данных, когда объект ABAP словаря и динамический объект консистентны, а объект базы данных не проходит проверку, можно осторожно выполнить операцию пересоздания динамического объекта (Runtime object), при этом взяв в качестве источника данных - таблицу на уровне базы данных. Напоминаю, что обычно для генерации динамического объекта используется объект ABAP словаря.
Для пересоздания необходимо войти в транзакцию SE14 в 000 манданте под пользователем DDIC. Задать необходимую таблицу и выбрать пункт меню "Таблица -> Реконструировать" или "Table -> Reconstruct" (рис. 7).
Так как после этой операции динамический объект скорее всего будет не соответствовать объекту в ABAP словаре, обязательно в SE11 активировать таблицу ещё раз, приведя в соответствие динамический объект и объект ABAP словаря.
Так же стоит иметь ввиду, что во время пересоздания объекта с данными на уровне базы данных, используется пространство в табличном пространстве PSAPUNDO (или PSAPROLL). А при пересоздании индекса для таблицы - пространство в табличном пространстве PSAPTEMP. При внесении изменений в большие таблицы имейте это в виду.
Возвращаясь к моей новогодней истории, я потратил 2 дня на решение проблемы. Изначально импорт и активация таблицы не произошли корректно из-за недостаточного места в PSAPROLL, а потом, после 3-4 автоматических попыток адаптировать таблицу на уровне базы данных, система уже не реагировала на несоответствия между словарями. Пришлось пересоздать динамический объект указанным выше способом. Расширить место во всех необходимых табличных пространствах, включая табличные пространства, в которых хранилась сама таблица и её индексы, и запустить процесс адаптации таблицы и её индексов в ручном режиме через SE14. 2 дня были потрачены из-за длительности обработки таблицы с таким количеством записей.
После решения всех проблем, обязательно проверьте динамический объект и объект базы данных через соответствующие пункты меню в SE11/SE14.
Полезные SAP ноты на данную тему:
Автор: Шиболов Вячеслав Анатольевич
Как вы помните, в SAP системе существует два словаря:
- ABAP Dictionary на уровне севера приложений,
- Database Dictionary на уровне базы данных.
Объект (таблица, индекс), созданный по всем правилам разработки в SAP системе, должен существовать в обоих словарях (рис 1).
Рис. 1. Два словаря системы. |
Давайте спустимся в кроличью нору немного глубже. :)
Когда я рассказывал про SAP Program buffer на уровне сервера приложений SAP, я упоминал про ABAP loads, которые генерируются для каждой ABAP программы и запускаются ABAP процессором в рабочих процессах инстанции. Для таблиц ситуация похожая. Для каждого объекта ABAP Dictionary (таблицы/домена/структуры и т.п.) существует динамический объект (Runtime object), который генерируется на основе записи из SAP словаря, и содержит техническую информацию об объекте. ABAP программа работает с элементами ABAP словаря не напрямую, а через динамические объекты.
Динамический объект генерируется автоматически при активации (транзакция SE11: ABAP словарь) новой таблицы или внесении изменений в существующую. Динамический объект можно просмотреть, если в транзакции SE11 выбрать пункт меню "Утилиты -> Динамический объект -> Просмотреть" (рис. 2).
Рис. 2. Просмотр динамического объекта для таблицы. |
Динамические объекты, которые являются активными в текущий момент времени, отображаются в виде двух частей (рис. 3):
- заголовок (хранится в таблице DDNTT),
- описание полей (содержится в таблице DDNTF).
Рис. 3. Пример динамического объекта для таблицы T000. |
Таблицы, в которых хранятся активные динамические объекты, существуют только на уровне базы данных и их нет в ABAP Dictionary. Поэтому посмотреть их структуру можно только в транзакции SE14 или на уровне базы данных. А для просмотра содержимого можно воспользоваться функциональным модулем DD_SHOW_NAMETAB (транзакция SE37). При обновлении объектов через транспортные запросы используется аналогичная пара таблиц для временного хранения неактивных объектов ABAP словаря - DDXTT и DDXTF.
Для того, чтобы проверить корректность динамического объекта, то есть соответствие его активному объекту ABAP словаря, необходимо в SE11 или SE14 выбрать пункт меню "Утилиты -> Динамический объект -> Проверить" (рис. 2). Результатом проверки будет окно вида (рис. 4).
Рис. 4. Результаты проверки динамического объекта. |
Вернемся обратно к основной теме.
Почему я всё это рассказал? А потому что объект в Database Dictionary создается на основе динамического объекта (Runtime object). То есть только для активного объекта ABAP словаря, который прошёл все проверки на уровне сервера приложений SAP. И, если мы хотим проверить объект базы данных, выбрав в SE11 пункт меню "Утилиты -> Объект базы данных -> Проверить" (рис. 5), то будет произведена сверка объекта из Database Dictionary и динамического объекта на уровне сервера приложений SAP.
Рис. 5. Проверка объекта базы данных. |
Таким образом, можно отобразить взаимосвязь объектов следующим образом (рис. 6).
Рис. 6. Работа с объектами в словарях данных системы SAP. |
Иногда во всей этой отлаженной машине возникают коллизии. В основном, при изменении объектов ABAP словаря - перенос транспортных запросов, импорт пакетов обновлений и так далее.
Хочу рассказать историю, которая произошла у меня на проекте в канун последнего Нового Года. Разработчик расширил таблицу на одно поле в системе разработки. Так как тестовой системы временно не было (тут можно вспомнить о важности тестовой системы), было принято решение импортировать запрос с изменениями в продуктивную систему перед новогодними каникулами. При импорте запроса разработчик не учёл, что за время работы с данной функциональностью в системе, таблица выросла на 200 миллионов записей (как у классика: за время в пути собачка могла подрасти). В итоге, импорт запроса проходил успешно. Активация изменений в таблице на уровне ABAP словаря тоже выполнялась успешно. Изменённый динамический объект генерировался, а вот дальше происходил сбой. Таблица на уровне базы данных упрямо не хотела адаптировать изменения - добавлять новое поле.
Что же может помочь при решении проблем с объектами ABAP словаря?
Во-первых, два инструмента - транзакции SE11 и SE14, которые можно использовать для локализации проблемы. Необходимо проверить статусы объекта на уровне всех словарей: динамический объект, таблицу на уровне базы данных. Нет ли где несоответствий и ошибок. При работе системы с некорректным динамическим объектом возникают дампы вида DDIC_TYPE_INCONSISTENCY, DDIC_TYPELENG_INCONSISTENT, DDIC_TYPE_REF_ACCESS_ERROR, TYPELOAD_NEW_VERSION и т.п.
Во вторых, при проблемах на уровне базы данных: для создания отсутствующих объектов или активации изменений на уровне базы данных необходимо использовать транзакцию SE14 (первый пост про транзакцию SE14).
В-третьих, при коллизиях с динамическим объектом можно попробовать удалить его (то есть записи из таблиц DDNTT и DDNTF) через функциональный модуль DD_NAMETAB_DELETE (транзакция SE37). После этого динамический объект можно попробовать заново сгенерировать через активацию таблицы в транзакции SE11.
Ну и наконец, при проблемах с объектом базы данных, когда объект ABAP словаря и динамический объект консистентны, а объект базы данных не проходит проверку, можно осторожно выполнить операцию пересоздания динамического объекта (Runtime object), при этом взяв в качестве источника данных - таблицу на уровне базы данных. Напоминаю, что обычно для генерации динамического объекта используется объект ABAP словаря.
Для пересоздания необходимо войти в транзакцию SE14 в 000 манданте под пользователем DDIC. Задать необходимую таблицу и выбрать пункт меню "Таблица -> Реконструировать" или "Table -> Reconstruct" (рис. 7).
Рис. 7. Инициирование пересоздание динамического объекта из таблицы на уровне базы данных. |
Так как после этой операции динамический объект скорее всего будет не соответствовать объекту в ABAP словаре, обязательно в SE11 активировать таблицу ещё раз, приведя в соответствие динамический объект и объект ABAP словаря.
Так же стоит иметь ввиду, что во время пересоздания объекта с данными на уровне базы данных, используется пространство в табличном пространстве PSAPUNDO (или PSAPROLL). А при пересоздании индекса для таблицы - пространство в табличном пространстве PSAPTEMP. При внесении изменений в большие таблицы имейте это в виду.
Возвращаясь к моей новогодней истории, я потратил 2 дня на решение проблемы. Изначально импорт и активация таблицы не произошли корректно из-за недостаточного места в PSAPROLL, а потом, после 3-4 автоматических попыток адаптировать таблицу на уровне базы данных, система уже не реагировала на несоответствия между словарями. Пришлось пересоздать динамический объект указанным выше способом. Расширить место во всех необходимых табличных пространствах, включая табличные пространства, в которых хранилась сама таблица и её индексы, и запустить процесс адаптации таблицы и её индексов в ручном режиме через SE14. 2 дня были потрачены из-за длительности обработки таблицы с таким количеством записей.
После решения всех проблем, обязательно проверьте динамический объект и объект базы данных через соответствующие пункты меню в SE11/SE14.
Полезные SAP ноты на данную тему:
- 1248769 - Inconsistency between database and ABAP Dictionary
- 2180238 - DDIC Inconsistency Check [VIDEO]
- 2048261 - Inactive runtime objects in the ABAP Dictionary
Автор: Шиболов Вячеслав Анатольевич
Спасибо, интересно.
ОтветитьУдалитьВячеслав, спасибо за статью!
ОтветитьУдалить