Текущее время: Чт, мар 28 2024, 17:59

Часовой пояс: UTC + 3 часа


Правила форума


ВНИМАНИЕ!

Вопросы по SAP Query и Quick View - сюда



Начать новую тему Ответить на тему  [ Сообщений: 5 ] 
Автор Сообщение
 Заголовок сообщения: Копирование манданта по RFC
СообщениеДобавлено: Пн, сен 12 2016, 14:51 
Менеджер
Менеджер
Аватара пользователя

Зарегистрирован:
Чт, мар 09 2006, 10:12
Сообщения: 565
Откуда: Волгодонск
Пол: Мужской
Пришлась разработать свой велосипед для копирования мандата между системами, хочу поделиться разработкой

Есть конечно штатное копирование, но оно нам по ряду причин не подходило, поэтому разработал своё. Ниже опишу вкратце характеристики:
Выполняется по RFC.
Запускается из системы источника данных.
Копируются только манданто-зависимые таблицы.
Если структура таблиц между системами отличается – копируются поля имеющиеся в обоих системах.

У нас оно запускается периодическим фоновым заданием в субботу ночью, за 10-12 часов копируется продуктив в тест.

Понадобится RFC соединение с сохранённым паролем, или доверительное соединение.

Запускается программой YDK_RFC_TABDATA_TRANSFER_RN
Изображение
«Имя таблицы» если не указать – будут выбраны для обработки все манданто-зависимые таблицы
«Количество потоков» — указываем количество потоков. В системе отправителе будет запущенно в фоне указанное количество программ YDK_RFC_TABDATA_TRANSFER_TH, в целевой системе работу потоков можно отслеживать через SM51
«Зачистить таблицу перед загрузкой» — по умолчанию установлена, если установлено в целевой системе данные из таблицы сначала удаляются (для некоторых таблиц требуется значительное время), а затем выполняется загрузка данных из системы источника. Если эту галку не устанавливать — в целевой системе могут остаться записи с старыми данными
«Игнорировать режим обработки» — в YDK_TRANSFER_TAB- CMODE может быть указан режим обработки таблицы: «Не копировать», «Не отчищать таблицу», «Копировать если изменилось количество записей». Эта галка позволяет игнорировать эту настройку.
«Метка таблицы» — проверяет значение в поле YDK_TRANSFER_TAB-LABL, можно использовать для отбора определённых таблиц
«Таблицы с режимом обработки» — проверяет значение поля YDK_TRANSFER_TAB- CMODE
«Статус последней обработки» — например позволяет отобрать таблицы при обработке которых возникли ошибки, и таким образом обработать их ещё раз.
«Количество записей в посл. обр», «Продолжительность обработки» — отбор по статистике собранной по таблице в предыдущей передаче данных.

Алгоритм
Изображение

Таблица YDK_TRANSFER_TAB - Настройка копирования таблиц
Изображение

Таблица YDK_TRANSFER - Лог копирования таблиц. (в логе хранится только последняя обработка таблицы)
Изображение

Интересные моменты:
Некоторые таблицы имеют очень большие размеры что существенно усложняет поставленную задачу:

Не возможно передать весь объём данных таблицы за один RFC вызов, поэтому надо данные передавать пакетами, что собственно не сложно организовать но RFC вызов вызывает неявный DB commit который рвёт выборку данных. Было протестировано множество вариантов, в конце концов в документации было найдено дополнение для call function KEEPING LOGICAL UNIT OF WORK «This addition is for internal use only. When this addition is used incorrectly, the worst case scenario may be a system shutdown, использование этого дополнения решило эту проблему, никаких проблем описанных в предупреждении не разу не возникало.

Code:
  OPEN CURSOR WITH HOLD cur FOR
    SELECT *
      FROM (tabname).
  DO.
    FETCH NEXT CURSOR cur INTO TABLE <tab> PACKAGE SIZE psize.
    IF sy-subrc <> 0. EXIT. ENDIF.
    CHECK NOT <tab> IS INITIAL.

    EXPORT tab FROM <tab> TO DATA BUFFER xstr.

    CALL FUNCTION 'YDK_RFC_TRANSFER_RECIVE'
      DESTINATION rfcdest
      KEEPING LOGICAL UNIT OF WORK " This addition is for internal use only. When this addition is used incorrectly, the worst case scenario may be a system shutdown.
      EXPORTING
        cluster               = xstr
      EXCEPTIONS
        system_failure        = 1
        communication_failure = 2
        OTHERS                = 5.
    IF sy-subrc <> 0.
      msg = |Ошибка при передаче данных { sy-subrc }|.
      EXIT.
    ENDIF.

    rowcount = rowcount + lines( <tab> ).
  ENDDO.
  CLOSE CURSOR cur.

Перед сохранением данных в целевом манданте, в целевой таблице надо удалить старые данные. Однако если таблица большая нельзя просо вызвать delete from <tabname> поскольку не хватит объёма roll back сегмента для отката транзакции и в результате дамп, поэтому удалять данные надо порциями с commit work между ними. Но к сожалению в синтаксисе delete from <tabname> нельзя указать сколько записей надо удалить, однако можно удалить используя таблицу с ключами полей DELETE (tabname) FROM TABLE <keytab>. Таким образом алгоритм такой: в цикле выбираем пачку ключевых полей в таблицу <keytab> затем удаляем их и так до тех пор пока в таблице не останется записей
Code:
  OPEN CURSOR WITH HOLD cur FOR
    SELECT (itfld)
      FROM (tabname).
  DO.
    FETCH NEXT CURSOR cur INTO TABLE <keytab> PACKAGE SIZE 1000.
    IF sy-subrc <> 0. EXIT. ENDIF.
    DELETE (tabname) FROM TABLE <keytab>.
    CALL FUNCTION 'DB_COMMIT'.
  ENDDO.
  CLOSE CURSOR cur.

Дополнение OPEN CURSOR WITH HOLD позволяет делать CALL FUNCTION ‘DB_COMMIT’ не прерывая выборку, если его не использовать при вызове DB_COMMIT курсор SQL запроса автоматически закроется. Однако это дополнение не срабатывает при RFC вызове… курсор всё равно закрывается.

Ещё одно замечание: как было выше написано «Если структура таблиц между системами отличается – копируются поля имеющиеся в обоих системах», для того чтоб это реализовать надо при загрузке данных сравнить структуру таблицы источника с таблицей приёмником, и если она отличается для переноса полей использовать move corresponding. Сначала для этих целей я хотел использовать классы cl_abap_datadescr=>describe_by_data и cl_abap_structdescr=>create( fct ) однако при тестировании системы оказалось, что работает это не удовлетворительно, поэтому я перешёл на классы cl_salv_bs_ddic=>get_components_by_data( <stab> ) и cl_salv_bs_ddic=>create_data_from_components. Насколько я помню (давно это было) проблема была связана с точностью описания и воспроизведения сложных структур – вложенные структуры/инклюды и т.п. правда и cl_salv_bs_ddic не безгрешен он спотыкается на полях в имени которых присутствует символ «-» но таких таблиц крайне мало.

Ну и напоследок:
Скопировать данные таблиц не достаточно, что в общем то было ожидаемо, требуется сделать ещё кое какие операции:

После копирования таблицы диапазонов номеров NRIV (и не только) необходимо сделать сброс буфера диапазона номеров , иначе номера будут выдаваться из сделанного буфера, что может привести duplicate record insert. При копировании этой таблицы, сброс выполняется автоматически, но может потребоваться сделать это в ручную, делается это транзакцией SM56 затем кнопка F5.

В некоторых таблицах хранится логческое имя системы (домен LOGSYS) , что приводит к тому что в целевой системе скопированные документы считаются прибывшими из чужой системы… поэтому сделана автоматическая замена в соотв. полях имени системы источника на имя системы приёмника

Установка:
Архив с транспортными файлами запроса на перенос
файл для SAPLink

_________________
Изображение Попытка не пытка


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Копирование манданта по RFC
СообщениеДобавлено: Пн, сен 12 2016, 17:09 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
Поскольку объём передаваемых по RFC данных довольно большой, наверно имеет смысл пользоваться сжатием данных, например, ФМ TABLE_COMPRESS и TABLE_DECOMPRESS. Они, в общем то, изначально для таких случаев и придуманы.
Вероятно и скорость обмена вырастет.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Копирование манданта по RFC
СообщениеДобавлено: Пн, сен 12 2016, 21:14 
Менеджер
Менеджер
Аватара пользователя

Зарегистрирован:
Чт, мар 09 2006, 10:12
Сообщения: 565
Откуда: Волгодонск
Пол: Мужской
Parazit написал:
Поскольку объём передаваемых по RFC данных довольно большой, наверно имеет смысл пользоваться сжатием данных, например, ФМ TABLE_COMPRESS и TABLE_DECOMPRESS. Они, в общем то, изначально для таких случаев и придуманы.
Вероятно и скорость обмена вырастет.

Хорошая идея, спасибо, сделаю протестирую...потом отпишусь

_________________
Изображение Попытка не пытка


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Копирование манданта по RFC
СообщениеДобавлено: Вт, сен 13 2016, 08:54 
Специалист
Специалист

Зарегистрирован:
Ср, дек 22 2010, 19:49
Сообщения: 114
Добавлю свои 5 копеек. Если религия позволяет, то, для быстрого удаления таблицы, можно использовать Native SQL + Truncate table.

_________________
Человек готов работать 24 часа в сутки, лишь бы ничего не делать.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Копирование манданта по RFC
СообщениеДобавлено: Вт, сен 13 2016, 12:22 
Менеджер
Менеджер
Аватара пользователя

Зарегистрирован:
Чт, мар 09 2006, 10:12
Сообщения: 565
Откуда: Волгодонск
Пол: Мужской
NeMurometz написал(а):
Добавлю свои 5 копеек. Если религия позволяет, то, для быстрого удаления таблицы, можно использовать Native SQL + Truncate table.

Truncate table - удалит данные во всех мандантах системы

_________________
Изображение Попытка не пытка


Принять этот ответ
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot]


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB