Я работал 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)
rahs
08.01.2018 15:11Статья не про сиквел, статья про то, как нельзя работать с данными.
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 и т.д. В общем тот еще квест был.
Dessloch
09.01.2018 09:57>>Данный пример для случаев, когда система уже спроектирована, и переделать ее вряд ли получится.
А зачем переделывать? Что плохого в том что центральный сервер сам забирает данные с периферийных? По-моему идеальный вариант.
sshmakov
09.01.2018 11:27Я работал web программистом в информационном центре одного из министерств с около сотней подведомственных учреждений. В каждом подведомственном учреждении на сервере была установлена десктоп программа, написанная на delphi, в которую ежедневно вносились данные. Раз в квартал каждому такому учреждению нужно было выгрузить dbf файл, приехать к нам в центр, по данным этой выгрузки получить отчеты и сдать их в министерство. Так было еще в досовской программе, а потом этот алгоритм просто ничего не меняя, перенесли в delphi. Выгрузка осуществлялась средствами Transact-SQL, и логика в ней была не простая.
Расскажу-ка я тоже одну историю. Все совпадения случайны и скорее всего вымышлены.
Одно министерство как-то заказало большой фирме, где я работал, Систему по оффлайновому сбору данных с подведомственных учреждений — набивка в dbf, перенос на диске в центр, загрузка в центральное хранилище. Продажа заказа была без моего участия, а когда его довели до меня, оказалось, что продали с реализацией на MS DTS. Типа там картинки, окошки, диаграмки потоков и преобразования данных, нажал кнопку и готово.
Стал я рисовать эти диаграмки, красиво, конечно. Но вот когда по этим диаграмкам создалось приложение и оно начало данные копировать, оказалось, что приложение сгенерировано на Visual Basic, огромное количество кода, а данные копирует оно по записям — прочитало запись в dbf, чего-то там подумало, записало в БД, опять подумало. То есть работало оно не просто медленно, а бесконечно долго, результата просто не дождешься, хотя данных там раз плюнуть, весь dbf в памяти помещался. Ковырялся я с этим неделю-две, уже не помню сколько, давно дело было, пакетной обработки не обнаружил, плюнул, и переписал на Delphi, получилась пара форм, один data module, и все летает. Ну диаграмок нет.
К сдаче проекта в министерстве начальство сказало распечатать (да-да, на бумаге) сгенеренные исходники на VB, потому что их было больше. Исходников на Delphi было-то всего ничего, не солидно как-то. И вот, сдача — в кабинете замминистра собралась толпа народу, все, кроме Самого, стоят, и куратор проекта со стороны заказчика, положа руку на папку с исходниками, говорит «Как видите, работа проделана большая...»
Drunik
09.01.2018 13:26в случае если данные есть только на продуктивном сервере
Видимо есть ещё малопродуктивный и совсем непродуктивный серверы?
А вообще становится сильно грустно от прочтения подобных статей — если на ключевые точки контроля сбора отчётности в министерствах ставят ответственных ит-специалистов, которые не знают основных возможностей sql-сервера в плане администрирования, а узнают об этом только погуглив, то всё очень плохо.
Это не претензия к автору, он то как раз молодец, поднял свой уровень знаний, а претензия к его руководству. Такие вещи делаются не на боевых серверах и не в авральном режиме.BigD
09.01.2018 21:06А что не так с продуктивом?
Drunik
10.01.2018 10:00продуктивный сервер. совсем не режет глаз?
BigD
10.01.2018 10:01Нет. У нас тысячи таких. Так и называем. И все называют. Прод и продуктив.
Drunik
10.01.2018 10:35-1Вы разницы между словами «продуктивный» и «прод», «продуктив» не замечаете? В первом случае — это неправильный перевод термина, а в вашем случае — это слэнг, перевод слова production. Давайте тогда введём в оборот все варианты перевода product — продуктовый, плодовый, результативный, а потом удивляться почему ракеты падают.
SmirnoffA
«Параллельно с этим в оффлайн режиме работала шина, которая скапливала данные со всех учреждений на единый центральный сервер. В шине были багги: она создавала дубли по первичному ключу и не все данные доходили.»
На этом остановился, дальше не читаю. Решил подождать второй редакции поста.
klirichek
Да полно-те вам… Вполне автомобильная тема: тут и шина есть, и багги...