Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
Исходная база MSSQL2000 SP4, к ней периодически (несколько раз в сутки) подключается PHP-код сайта, чтобы забрать порядка 50-60 селектов с измененёнными данными (а иногда и полная перезаливка данных) в собственную базу MySQL (в MSSQL ничего не пишет, кроме данных о своём подключении - начало, окончание, успех или ошибка). Время работы соединения порядка 5 минут при скорости канала 1 Mbit (в будущем может достигать часа, а при полной перезаливке данных и суток). Стоит задача заблокировать от изменений данные (таблицы), на которых основаны селекты, с момента старта соединения PHP-кода и до его окончания. Также необходимо реализовать автоматическую разблокировку по таймауту, которая должна сработать, например, при обрыве соединения. Как грамотно реализовать этот механизм передачи?

Механизм выборки обновлённых данных основан на журналировании изменений с сохранением полей timestamp. Предплагается, что в начале соединения PHP-код запросит максимальную версию записи последней сессии, сообщит о старте новой сессии запуском хранимки, таблицы заблокируются от изменений, выберет данные, сообщит об успешном окончании сессии (или ошибке) запуском хранимки, после чего текущее значение @@DBTS будет сохранено как максимальная версия записи для начала следующей сессии (при условии блокирования всех таблиц, участвующих в селектах), и таблицы разблокируются. Есть также вариант подсчёта максимальной версии записи по забираемым селектам, хотя это лишние вычисления.

Второй вариант может заключаться в том, что PHP-код запускает одну хранимку, из которой считывает все селекты. Проблема в том, что мне неизвестны возможности PHP, а PHP-разработчик не знает MSSQL. Также мне непонятно, как грамотно блокировать данные с автоматической аварийной разблокировкой.

Как реализовать этот механизм синхронизации?
27 окт 11, 09:00    [11506543]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo,

хотелось бы уточнить: у вас 50-60 таблиц, и вы хотите их все заблокировать на сутки? Сурово... Для блокировки от изменений одной таблицы достаточно указать в запросе подсказку TABLOCK
27 окт 11, 09:16    [11506578]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
nicomo,

Так как снапшотов нет в 2000 то проще бэкап продуктива , отправка его, восстановление и копирнование локально в майскул ?
Ибо ни блокировка продуктива на сутки, ни сутки перенос данных - не комильфо
27 окт 11, 09:24    [11506593]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
iljy
nicomo,

хотелось бы уточнить: у вас 50-60 таблиц, и вы хотите их все заблокировать на сутки? Сурово... Для блокировки от изменений одной таблицы достаточно указать в запросе подсказку TABLOCK

Таблиц порядка 25, к каждой прилагается отдельная таблица журнала изменений, итого 50. Блокировать на сутки необходимо будет только для полной перезаливки в "ручном режиме" на случай рассинхронизации. Эта редкая ситуация и сутки максимальный интервал. Фактически, необходимо реализовать 2 механизма синхронизации - частичный (несколько раз в сутки) и полный (редкий на случай рассинхронизации).
Блокировать мне необходимо весь набор таблиц с момента старта сессии синхронизации, чтобы PHP-код забрал согласованные данные.
27 окт 11, 09:27    [11506603]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
Ken@t,

Повторюсь, что основной механизм - частичная синхронизация, одна сессия будет занимать несколько минут.
27 окт 11, 09:29    [11506611]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo,

работайте в TIL SNAPSHOT и не морочьте себе голову.
27 окт 11, 10:00    [11506764]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo,

хотя не, у вас же 2000.... Тогда бида, заблокировать все таблицы одновременно у вас не получится даже на SERIALIZABLE. Самое простое - это в начале сессии выполнить что-то типа
select top 0 * from Table_1(TABLOCK),Table_2(TABLOCK)....
27 окт 11, 10:01    [11506778]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]

Guest
1) если целевая система стоит на win операционке - поставить на ней msde, на системе источнике завести вторую базу в неё наладить репликацию нужных таблиц, бекапить реплицированные таблицы по нужному расписанию. забирать бекапы с источника переносить на целевую систему, там разворачивать в msde и от туда уже забирать нужные данные.
минусы - ограничение на размер поддерживаемой базы для msde - 2 гига.
плюсы - один механизм для "полного" и "частичного" обновления.

2) не win операционка. также создается вторая база на системе источнике. По расписанию формируются файлы дампов для MySQL в текстовом варианте. PHP их "забирает" и заливает в MySQL.
где то так :)
27 окт 11, 10:03    [11506786]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]

Guest
да забыл добавить также во второй базе формировать и признак синхронизации. его отдавать в MySQL, и потом получив его-же от MySQl - формировать новые данные, "начиная" от принятой метки.
27 окт 11, 10:06    [11506804]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
iljy,

Вы имеете ввиду открыть этот селект на стороне PHP и держать его открытым, пока остальные селекты выбираются по одному? В принципе это тоже вариант, хотя хотелось бы, чтобы блокировкой управлял код MSSQL. А как реализовать аварийную разблокировку при обрыве соединения? Разорвёт ли это соединение MSSQL при бездействии и при каких условиях?
27 окт 11, 10:42    [11506998]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
`ё,

От варианта использования посредников (вторая база данных, текстовые дампы) было решено отказаться, чтобы не тратить лишнее время. На данный момент PHP-код бодро пробегает по селектам и заливает их в свою базу MySQL. Всё что нужно - это грамотно реализовать блокировку таблиц с последующей разблокировкой, в том числе при обрыве соединения.
27 окт 11, 10:47    [11507044]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
--------------------------------
Guest
А зачем все блокировать.
На мой взгляд нужно просто добавить в каждую таблицу поле timestamp.
В начале сессии запросить текущее значение timestamp t1.
Такое жэ значение для предыдушего сеанса обозначим как t0.
Тогда нужно просто отобрать записи с timestamp между t0 и t1.
В конце сеанса установить t0=t1.
27 окт 11, 11:01    [11507186]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]

Guest
если вы хотите пройти весь "путь" получения синхронизированных данных через блокировки, я вам мешать не буду :)
намек - при чтении напрямую из пхп идёт синхронный процесс, при использовании получается что-то типа асинхронного.
"не тратить лишнее время" - на что?

если пойдёте по пути хинтов - с прекращением сессии снимаются все выставленные хинты.

а сколько человек работаю с базой mssql?
27 окт 11, 11:05    [11507225]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
--------------------------------,

Могут закачаться рассогласованные данные. Например, закачали таблицу1, качаете таблицуN-1, произошла запись в таблицу1 и таблицуN (а в ней ссылка на новую запись таблицы1), качаете таблицуN, получили запись со ссылкой на несуществующую запись в таблице1. Т.е. данные на стороне PHP будут рассогласованы.
27 окт 11, 11:07    [11507255]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo
iljy,

Вы имеете ввиду открыть этот селект на стороне PHP и держать его открытым, пока остальные селекты выбираются по одному? В принципе это тоже вариант, хотя хотелось бы, чтобы блокировкой управлял код MSSQL. А как реализовать аварийную разблокировку при обрыве соединения? Разорвёт ли это соединение MSSQL при бездействии и при каких условиях?

Я имею ввиду скачивать данные в одной транзакции и первой командой поставить такой вызов. При разрыве соединения естественно транзакция откатится.
27 окт 11, 11:18    [11507354]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
`ё,

Намёк к сожалению не понял. Механизм синхронизации уже готов, к каждой таблице прикручен журнал, из него можно делать выборки, какие записи вставить, обновить и удалить после определённой версии записи.
Не тратить лишнее время - на разработку звеньев-посредников, включая механизмы репликации, очередей, извещателей и т.д.
ТЗ позволяет синхронизироваться ночью (частично) и в выходные (полная).

Намёк, если можно поясните. По пути не ходил, интересуют всевозможные грабли. На деле нужно 100% рабочее решение и фактически до конца недели.

В базе работают 50 человек.
27 окт 11, 12:10    [11507828]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
invm
Member

Откуда: Москва
Сообщений: 9844
Позволю себе дополнить.
Способ, предложенный iljy, будет работать, если TIL транзакции будет минимум repeatable read. На TIL read committed нужно так
select top 0 * from Table_1(TABLOCK, HOLDLOCK),Table_2(TABLOCK, HOLDLOCK)....
Но это все равно не гарантирует согласованности, ибо порядок наложения блокировок не определен. Если логика системы позволяет, то лучше это сделать одиночными селектами, в порядке, обеспечивающем согласованность данных при вычитке.
А еще лучше, использовать штатный механизм -- гетерогенную репликацию транзакций.
27 окт 11, 12:15    [11507882]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
В резерве держу такое решение:
1) PHP-код запускает хранимую процедуру StartSession с параметром таймаута, которая:
1.1) проверяет, разрешено ли в это время синхронизироваться и с таким таймаутом;
1.2) делает запись открытой сессии в спецтаблицу (время и таймаут);
1.3) возвращает успех и максимальную версию записи предыдущей сессии, либо ошибку при запрете.
2) На все таблицы вешаются триггеры, которые при открытой сессии до истечения таймаута запрещают изменение данных, сообщая пользователям об ошибке на человеческом языке, в том числе указывая время, когда действие будет точно разрешено. По истечении таймаута или закрытии сессии изменения разрешены.
3) PHP-код перебирает селекты, используя полученную версию записи, и выбирает данные.
4) PHP-код завершает сессию запуском процедуры FinishSession с параметром кода успеха или ошибки. Если сессия не завершена по таймауту, то возвращается успех, делается запись закрытой сессии в спецтаблицу с фиксацией максимальной версии записи (@@DBTS) для следующей сессии, иначе возвращается ошибка.

Решение хорошо тем, что абсолютно понятно и безграбельно. В тоже время лепить триггеры (хоть их можно и автоматически сгенерировать) считаю не самой лучшей идеей. Хотелось бы обойтись стандартными возможностями блокировок, получив в итоге такое же ясное и безграбельное решение.
27 окт 11, 12:42    [11508169]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
--------------------------------
Guest
nicomo
Могут закачаться рассогласованные данные. Например, закачали таблицу1, качаете таблицуN-1, произошла запись в таблицу1 и таблицуN (а в ней ссылка на новую запись таблицы1), качаете таблицуN, получили запись со ссылкой на несуществующую запись в таблице1. Т.е. данные на стороне PHP будут рассогласованы.

Не могут. Если запись изменится после запроса t1, то у нее поменяется timestamp. Он будет больше t1 и она не попадет в выборку.
27 окт 11, 12:45    [11508208]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo,

вы даже приблизительно не представляете, сколько граблей содержит ваше "простое и безграбельное". А самое главное - проблемы одновременной блокировки таблиц оно все равно не решает.
27 окт 11, 12:46    [11508217]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
iljy,

Это точно, не представляю. И даже уверен в его работоспособности, как и в выполнении функции блокировки данных от изменения, пока их считывает другая сторона. Разуверьте меня, пожалуйста.
27 окт 11, 13:02    [11508396]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo,

данные от изменения заблокирует приведенный мной SELECT, без всяких триггеров и прочих бубнов. В худшем случае он чреват дедлоком, тогда его надо будет повторить. Также он дает страховку от всяких происшествий типа разрыва соединения и прочего. В вашем же варианте при любых проблемах на канале поведение становится весьма запутанным. Ну и просто модификация схемы потенциально очень проблемная операция (например - мало ли , какие там еще триггеры висят!). Впрочем любителей лазить по деревьям в ластах возможные неудобства никогда не смущали.
27 окт 11, 13:22    [11508597]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
--------------------------------,

Ну тогда запись в таблицуN обновит ранее добавленную в интервал от t0 до t1 запись. Поскольку новый t > t1, запись не закачается в этом сеансе (уже рассогласование), и может никогда не закачаться, если её всякий раз обновляит после старта сессии но до закачки.
27 окт 11, 13:24    [11508609]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
nicomo
Member

Откуда:
Сообщений: 37
iljy
nicomo,

данные от изменения заблокирует приведенный мной SELECT, без всяких триггеров и прочих бубнов. В худшем случае он чреват дедлоком, тогда его надо будет повторить. Также он дает страховку от всяких происшествий типа разрыва соединения и прочего. В вашем же варианте при любых проблемах на канале поведение становится весьма запутанным. Ну и просто модификация схемы потенциально очень проблемная операция (например - мало ли , какие там еще триггеры висят!). Впрочем любителей лазить по деревьям в ластах возможные неудобства никогда не смущали.

Я свой вариант потому и считаю резервным, что не хочу триггеры лепить, которые производительности не добавят. Но вы явно о нём ошибочно рассуждаете. Триггеры типа AFTER порядка First будут откатывать транзакцию, и никаким другим триггерам не помешают. Во всяком случае все мои триггеры рассчитаны, что может быть добавлен любой новый, который может откатить транзакцию. Также этот вариант даёт полную гарантию от каких-либо проблем на канале, от дедлоков и любого странного проявления механизма блокировок, которое иногда имеет место быть.

Тем не менее, я "копаю" в направлении, указанном вами, и вполне благодарен за него. Но мне нужно 100% рабочее решение в ограниченное время, а многое неясно.

Например, следующее:
1) Какие артефакты могут быть от наложения таким образом блокировок? Например, если другие сеансы наложат свои блокировки и т.д. При каких условиях данная блокировка может слететь (и как об этом узнать, если это возможно)? Что вы имеете ввиду "В худшем случае он чреват дедлоком, тогда его надо будет повторить."?
2) Какой мне подготовить интерфейс в виде каких объектов для вызова из PHP? В виде одной хранимой процедуры, которая будет выполнять весь код и передавать все селекты?
3) Как на стороне MSSQL управлять таймаутом в таком алгоритме, чтобы не допустить чрезмерно долгой блокировки (если по каким-то причинам PHP код будет долго сохранять соединение)?
27 окт 11, 14:07    [11509026]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать одностороннюю синхронизацию из MSSQL в MySQL через PHP-код?  [new]
iljy
Member

Откуда:
Сообщений: 8711
nicomo
1) Какие артефакты могут быть от наложения таким образом блокировок? Например, если другие сеансы наложат свои блокировки и т.д. При каких условиях данная блокировка может слететь (и как об этом узнать, если это возможно)? Что вы имеете ввиду "В худшем случае он чреват дедлоком, тогда его надо будет повторить."?
2) Какой мне подготовить интерфейс в виде каких объектов для вызова из PHP? В виде одной хранимой процедуры, которая будет выполнять весь код и передавать все селекты?
3) Как на стороне MSSQL управлять таймаутом в таком алгоритме, чтобы не допустить чрезмерно долгой блокировки (если по каким-то причинам PHP код будет долго сохранять соединение)?

1. Почитайте про типы блокировок и их совместимость.
2. Как хотите. Главное, что сеанс должен открывать транзакцию и первым делом выполнять блокирующий SELECT. Дальше делайте в нем что хотите, потом закрывайте транзакцию и сеанс.
3. В каком смысле? Хотите закрывать соединение по истечении определенного времени? Или установить таймаут для других соединений? 2е - смотрите LOCK_TIMEOUT. Первое сложнее, но можно например настроить задание, которое в определенный момент времени запустится и убьет ваше соединение, но, по-моему, это излишне, если клиент отвалится в момент получения данных, то сервер быстро это обнаружит.
27 окт 11, 14:35    [11509322]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить