![]() |
|
|
![]()
|
|
| Гость_BasilL |
|
|||
|
Unregistered |
Требуется на некоторое время запретить запись в таблицу MS SQL. При этом чтение разрешается.
Доступ через SDAC v3. Подробнее: есть некая таблица "CurrentDate". В ней хранится рабочая дата. На рабочих местах клиентов в глобальной переменной хранится "своя" дата - у разных клиентов она может быть разной. При определенных условиях у конкретного клиента возникает необходимость в таких действиях: 1) сначала записать в таблицу на серваке "свою" дату (так, чтобы транзакция завершилась и сервер принял запись и увидел изменение) 2) после этого начинается новая транзакция (где и производится все, что клиенту надо), по окончании этой транзакции, дата в таблице на сервере снова возвращается та, которая была. Проблема возникает в том случае (теоретически), когда между шагами 1) и 2) другой клиент меняет дату в таблице на сервере, то шаг 2) у первого клиента отрабатывается неправильно. Вот и надо на какое-то время (как-правило, секунды) запретить всем запись в таблицу с датой. p.s. Объединять транзакции и вставлять что-то вроде "UPDLOCK" не подходит. В BDE был предусмотрен монопольный доступ и Table.Lock. Нет ли чего-нибудь похожего в связке SDAC - MS SQL? Вроде бы, более-менее понятно описал суть проблемы. Заранее, спасибо. |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
SET TRAN ISOLATION LEVEL SERIALIZABLE
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
| BasilL |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 84 Регистрация: 26.5.2005 Где: Челябинск обл. Репутация: нет Всего: 1 |
To Vit
Так не прокатит. Нелься создавать дополнительную транзакцию - в это время проходит другая транзакция, а пока она не завершена, новую я стартовать не могу, а применить "SET TRAN ISOLATION LEVEL SERIALIZABLE" к запущенной на шаге 2) транзакции тоже нельзя - это ничего не даст - таблица, запись в которую надо блокировать в ней не задействована. К тому же транзакция на шаге 2) не использует ХП, а прописать "SET TRAN ISOLATION LEVEL SERIALIZABLE" в компоненты MSTable и MSQuery от SDAC вроде-бы некуда. Вот кусок кода, когда отрабатывает транз. на шаге 2):
т.е. в это время производится запись из нескольких виртуальных таблиц в таблицы на сервере. И надо быть уверенным, что таблица с датой в это время не изменялась. |
||||
|
|||||
| Vit |
|
||||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Хм... тогда только hint на запросах ставить... больше по-моему никак... И вообще такие действия должны ИМХО быть в пределах одной транзакции...
Открыть таблицу запросом:
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
||||
|
|||||
| BasilL |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 84 Регистрация: 26.5.2005 Где: Челябинск обл. Репутация: нет Всего: 1 |
To Vit
Так вот, нету у меня в этой транзакции запросов, не нужны они. Если только специально для хинт-а какой-нибудь в начале транзакции запускать... типа Select * from <таблица_с_датой> with (tablockx). А? Как-то не очень расиво получается. Тут в одной статейке только что прочитал, что есть такая хп - sp_getapplock ("...Смысл ее в следующем – блокировка произвольного ресурса..."). Нельзя ли это как-то применить? Это сообщение отредактировал(а) BasilL - 23.6.2005, 20:15 |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Не бывает транзакций без запросов... в отношении SQL Server... Он просто не позволит делать ничего кроме запросов. Даже если ты открываешь таблицу каким-то компонентом типа Table в отличие от парадокса реально выполняется запрос типа Select * From Table, поэтому замени свои компоненты Table на запросы и используй блокировки. -------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
| BasilL |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 84 Регистрация: 26.5.2005 Где: Челябинск обл. Репутация: нет Всего: 1 |
Я понимаю, что по-сути, нет транзакции без запросов, но дело не в этом.
Нельзя заменить Table на Query, я не смогу написать SQL.Text типа "insert into ... from... , поскольку from-то как раз и нету. В транзакции я переписываю некий набор записей из компонента TVirtualTable в TTable. TVirtualTable - это виртуальная таблица из набора SDAC (поэтому его и выбрал), на сервере этих данных нет и быть не может, они появятся там только после Table.post. Вот и выходит, что нельзя все это описать запросом. p.s. Insert ... values тоже не подойдет. |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Ничего не понял... Извини я не знаком с этим пакетом... Не понимаю что за виртуальные таблицы... Для их осуществления можно использовать View, temp таблицы и т.п. И любой компонент Table абсолютно эквивалентен live запросу Select * From Table
Добавлено @ 21:35 Кажись понял... Это решаемо при помощи запросов, псевдокод такой:
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
| BasilL |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 84 Регистрация: 26.5.2005 Где: Челябинск обл. Репутация: нет Всего: 1 |
2Vit
Согласен с тобой, так работать будет. Вот только лочить надо не ту таблицу в которую добавляю запись, а совсем другую. (таблица, которую надо блокировать, и таблица в которую пишу - это совершенно разные, не связанные между собой таблицы). Объясню смысл: так, как ты написал (или как у меня сейчас, похоже) в таблицу я добавляю запись (записи). Перед этим запускается функция (if Check_mpz_kol() then ... - см. код), в которой сначала в таблицу <CurrentDate> пишется определенная дата, затем делается запрос к серверу, который возвращает определенный набор данных (они зависят от даты), эти данные проверяются, и если они удовлетворяют определенным условиям, функция возвращает true, и выполнение транзакции продолжается (тут и начинается перенос данных из виртуальной таблицы, который ты описал), если нет - откат. Так вот, таблицу с датой и надо залочить на время выполнения функцией проверки, точнее даже достаточно на время получения данных, которые проверяем - чтобы быть уверенными, что эти данные соответсвуют установленной дате. После проверки таблицу желательно разблокировать, чтобы не держать других клиентов - проверка идет быстро, а вот до конца транзакции еще долго. А если я в начало основной транзакции (где переносятся записи из вирт. табл.) добавлю выполнение запроса типа "select * from CurrentDate with (tablelockx)", то, конечно, нужного результата добьюсь, но буду долго держать таблицу блокированной - это нежелательно. А вставить такой запрос в процедуру проверки не получиться - сервер не даст запустить вторую транзакцию, в это время уже есть активная транзакция; на всякий случай пробовал - сервак, ессно, ругается: user transaction already in progress. з.ы. логика формирования проверяемых данных организована на сервере, перенести ее на клиента нельзя, поэтому сделать что-то вроде TQuery с параметром, в который и ложить дату не выйдет. Странная, наверное, у меня ситуация. А что делать? |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Мдя... даже не знаю... Может над архитектурой подумать?
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
| BasilL |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 84 Регистрация: 26.5.2005 Где: Челябинск обл. Репутация: нет Всего: 1 |
Вот и я не знаю.
А может быть лучше создать некий пользовательский ресурс и блокировать его sp_getapplock? Это сообщение отредактировал(а) BasilL - 25.6.2005, 12:33 |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 14 Всего: 207 |
Похоже на то
-------------------- With the best wishes, Vit I have done so much with so little for so long that I am now qualified to do anything with nothing Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru |
|||
|
||||
![]()
|
| Правила форума "Delphi: Базы данных и репортинг" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами Обязательно указание: 1. Базы данных (Paradox, Oracle и т.п.) 2. Способа доступа (ADO, BDE и т.д.)
FAQ раздела лежит здесь! Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |