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

Я работал web программистом в информационном центре одного из министерств с около сотней подведомственных учреждений. В каждом подведомственном учреждении на сервере была установлена десктоп программа, написанная на delphi, в которую ежедневно вносились данные. Раз в квартал каждому такому учреждению нужно было выгрузить dbf файл, приехать к нам в центр, по данным этой выгрузки получить отчеты и сдать их в министерство. Так было еще в досовской программе, а потом этот алгоритм просто ничего не меняя, перенесли в delphi. Выгрузка осуществлялась средствами Transact-SQL, и логика в ней была не простая.

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

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

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

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

Для создания связанного сервера нужно выполнить скрипт:

EXEC master.dbo.sp_addlinkedserver @server = N'MY_SERV_1',  @datasrc=N'192.168.1.1'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'MY_SERV_1',@useself=N'False',@locallogin='sa',@rmtuser='sa',@rmtpassword='1111111'

Параметры сервера

server – имя сервера, по которому мы будем к нему обращаться
@datasrc – ip адрес удаленного сервера

Параметры авторизации сервера

@rmtsrvname – имя, которое мы назначили серверу
@locallogin – имя учетной записи
@rmtpassword – пароль учетной записи
@rmtuser – пользователь БД

При создании связанного сервера часть параметров по доступу к данным проставляется в значение 'false' (список параметров вы можете посмотреть тут ). Если вам нужно, какие-то параметры установить в значение 'true', например 'rpc'и 'rpc out', то к скрипту создания нужно добавить следующие команды:

EXEC master.dbo.sp_serveroption @server=N'MY_SERV_1', @optname=N'rpc', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server= N'MY_SERV_1', @optname=N'rpc out', @optvalue=N'true'
GO

Обратите внимание, что в параметре server мы указали то имя, которое мы дали связанному серверу.

В итоге скрипт создания связанного сервера целиком выглядел бы так

EXEC master.dbo.sp_addlinkedserver @server = N'MY_SERV_1',  @datasrc=N'192.168.1.1'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'MY_SERV_1',@useself=N'False',@locallogin='sa',@rmtuser='sa',@rmtpassword='1111111'
GO
EXEC master.dbo.sp_serveroption @server=N'MY_SERV_1', @optname=N'rpc', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server= N'MY_SERV_1', @optname=N'rpc out', @optvalue=N'true'
GO

Запрос к созданному серверу выполняется, так же как и к своему, но в начале указывается префикс с именем связанного сервера. Так же при обращении нужно указывать имя схемы (в примере ниже схема называется ‘DBO’):

SELECT * FROM [MY_SERV_1'].MY_BASE.DBO.MY_TABLE 

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

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

Комментарии (13)


  1. SmirnoffA
    08.01.2018 12:41

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


    1. klirichek
      09.01.2018 12:59

      Да полно-те вам… Вполне автомобильная тема: тут и шина есть, и багги...


  1. rahs
    08.01.2018 15:11

    Статья не про сиквел, статья про то, как нельзя работать с данными.


    1. Daar
      08.01.2018 20:02
      +1

      Согласен… сталкивался с подобным в этих структурах. В некоторых все еще работает ПО написанное на Foxpro, Clipper, Paradox… для хранения используются dbf или еще что пострашнее типа Btrieve который развернут на… Novell Netware. И причем за «поддержку» платят шестизначные суммы. На вопрос «Зачем так?!» к одному «поддерживателю», получен был обычный ответ «Работает же! Кто придумал, 10 лет назад уволился. Переписывать дорого.». И когда нам нужно было прикрутить это к вебу, они сказали просто «API простое… вот вам доступ по RDP, запускаете вот этот bat'ник вот с такими параметрами, вот в этой папке появляется файл dbf, из него данные и берете». Ну и потом выяснилось что все русские данные хранятся в CP866, а на некоторых старых компах стоит keyrus, и ввиду этого в русских словах используются английские буквы типа: a, o, p, e, c и т.д. В общем тот еще квест был.


  1. Dessloch
    09.01.2018 09:57

    >>Данный пример для случаев, когда система уже спроектирована, и переделать ее вряд ли получится.
    А зачем переделывать? Что плохого в том что центральный сервер сам забирает данные с периферийных? По-моему идеальный вариант.


  1. sshmakov
    09.01.2018 11:27

    Я работал web программистом в информационном центре одного из министерств с около сотней подведомственных учреждений. В каждом подведомственном учреждении на сервере была установлена десктоп программа, написанная на delphi, в которую ежедневно вносились данные. Раз в квартал каждому такому учреждению нужно было выгрузить dbf файл, приехать к нам в центр, по данным этой выгрузки получить отчеты и сдать их в министерство. Так было еще в досовской программе, а потом этот алгоритм просто ничего не меняя, перенесли в delphi. Выгрузка осуществлялась средствами Transact-SQL, и логика в ней была не простая.

    Расскажу-ка я тоже одну историю. Все совпадения случайны и скорее всего вымышлены.

    Одно министерство как-то заказало большой фирме, где я работал, Систему по оффлайновому сбору данных с подведомственных учреждений — набивка в dbf, перенос на диске в центр, загрузка в центральное хранилище. Продажа заказа была без моего участия, а когда его довели до меня, оказалось, что продали с реализацией на MS DTS. Типа там картинки, окошки, диаграмки потоков и преобразования данных, нажал кнопку и готово.

    Стал я рисовать эти диаграмки, красиво, конечно. Но вот когда по этим диаграмкам создалось приложение и оно начало данные копировать, оказалось, что приложение сгенерировано на Visual Basic, огромное количество кода, а данные копирует оно по записям — прочитало запись в dbf, чего-то там подумало, записало в БД, опять подумало. То есть работало оно не просто медленно, а бесконечно долго, результата просто не дождешься, хотя данных там раз плюнуть, весь dbf в памяти помещался. Ковырялся я с этим неделю-две, уже не помню сколько, давно дело было, пакетной обработки не обнаружил, плюнул, и переписал на Delphi, получилась пара форм, один data module, и все летает. Ну диаграмок нет.

    К сдаче проекта в министерстве начальство сказало распечатать (да-да, на бумаге) сгенеренные исходники на VB, потому что их было больше. Исходников на Delphi было-то всего ничего, не солидно как-то. И вот, сдача — в кабинете замминистра собралась толпа народу, все, кроме Самого, стоят, и куратор проекта со стороны заказчика, положа руку на папку с исходниками, говорит «Как видите, работа проделана большая...»


  1. vba
    09.01.2018 13:21

    Кошмар, связанные сервера в 2018 году это просто жесть. Их использование чуть ли не совбез ООН запретил.


    1. BigD
      09.01.2018 21:05

      А что делать… используем, правда не в такой схеме, как у ТС


  1. Drunik
    09.01.2018 13:26

    в случае если данные есть только на продуктивном сервере

    Видимо есть ещё малопродуктивный и совсем непродуктивный серверы?

    А вообще становится сильно грустно от прочтения подобных статей — если на ключевые точки контроля сбора отчётности в министерствах ставят ответственных ит-специалистов, которые не знают основных возможностей sql-сервера в плане администрирования, а узнают об этом только погуглив, то всё очень плохо.
    Это не претензия к автору, он то как раз молодец, поднял свой уровень знаний, а претензия к его руководству. Такие вещи делаются не на боевых серверах и не в авральном режиме.


    1. BigD
      09.01.2018 21:06

      А что не так с продуктивом?


      1. Drunik
        10.01.2018 10:00

        продуктивный сервер. совсем не режет глаз?


        1. BigD
          10.01.2018 10:01

          Нет. У нас тысячи таких. Так и называем. И все называют. Прод и продуктив.


          1. Drunik
            10.01.2018 10:35
            -1

            Вы разницы между словами «продуктивный» и «прод», «продуктив» не замечаете? В первом случае — это неправильный перевод термина, а в вашем случае — это слэнг, перевод слова production. Давайте тогда введём в оборот все варианты перевода product — продуктовый, плодовый, результативный, а потом удивляться почему ракеты падают.