Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Отслеживание длостижения лимита в БД


Автор: Zamuta 11.4.2007, 01:04
Всем здрасьте.
Есть задача. Требуется при достижении, например 1000 записей в одной таблице выполнить определённые действия в коде, например раскидать данные из этой таблицы по другим.

Как это лучше сделать?

1. Ставить max_rows=1000 и при попытке записать 1001 строку ловить эксепшен, но где уверенность, что это будет эксепшн именно по этой причине? Можно тогда отловить getErrorCode() , но как-то криво это всё.

2. Писать листенер который опять же всё время будет дёргать бд. (хотя это уже не листенер)  тоже криво.
 
Есть ли уже испытанные решения? 

Автор: polosatij 11.4.2007, 02:57

может простой TRIGGER на таблицу повесить? тогда можно вообще забыть про явакод..
Смотри свою Базуданных + Trigger  smile 

Автор: nornad 11.4.2007, 03:53
Цитата(Zamuta @  11.4.2007,  04:04 Найти цитируемый пост)
1. Ставить max_rows=1000 и при попытке записать 1001 строку ловить эксепшен, но где уверенность, что это будет эксепшн именно по этой причине? Можно тогда отловить getErrorCode() , но как-то криво это всё.

А кто тебе мешает бросать свой эксепшн? Тогда уж точно будешь знать, по какой причине он вывалился. ;)
Но вообще идея так себе.

Если скажешь, для чего тебе это требуется, то будет проще что-либо советовать. А так можно устроить только спиритический сеанс и нагадать триггеры, эксепшены, листенеры, ветки кода...

Автор: Zamuta 11.4.2007, 10:09
Цитата
Если скажешь, для чего тебе это требуется, то будет проще что-либо советовать


Я же говорю, при достижении N  кол-ва записей в таблице выполнить действия в коде. Примером может служить, например такая ситуация, на торговом складе закончилось заранее известное место и теперь всю продукцию пишем уже в другую бд. Т.е. на странице я должен видеть что первая бд заполнилась а в коде выполнилось CREATE TABLE ....т.е. создалась новая бд автоматически...

Автор: tux 11.4.2007, 10:45
Zamuta, CREATE TABLE создает таблицу, БД - это контейнер для таблиц. Честно говоря, я плохо понимаю зачем может такое понадобиться. Почему бы в таблице не завести дополнительное поле, указывающее на каком торговом складе хранится продукция. И не нужно никаких таблиц создавать. Я вижу всего две реальные причины переноса записей между таблицами: 
  • создание архива, чтобы ускорить производительность выполнения запросов в основной таблице
  • ограниченность размера табличных пространств, в которых таблицы находятся.
А иначе это просто способ создать себе проблемы.

Автор: Zamuta 11.4.2007, 17:57
Цитата
Честно говоря, я плохо понимаю зачем может такое понадобиться
 , понимаю, но это есть прямая задача, ситуация про склады приведена лишь для примера. 

Как вам такое решение? 
Перед добавлением новой строки в таблицу вытягиваем из resultset'a   getRowId(1000) или getInt(1000) и если не удалось, то значит кол-во строк < 1000.

Вопрос в том чьими средствами это лучше сделать? В БД или коде? 

Автор: Stampede 11.4.2007, 18:21
Цитата(Zamuta @  10.4.2007,  16:04 Найти цитируемый пост)
Есть ли уже испытанные решения? 


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

В чем проблема с отслеживанием кол-ва записей? А в том, что это подразумевает частое выполнение "SELECT COUNT(*)". А это отнюдь не безобидная операция: она блокирует всю таблицу и может выполняться достаточно долго.

Тут можно придумать много разных вариантов: например, преаггрегирование количества записей в нужной тебе таблице через триггер, или периодический опрос таблицы отдельным тредом/заданием, да и мало ли чего еще. Но чтобы что-то советовать, нужно знать, чего мы хотим добиться и нафига вообще это надо. Так что колись smile

Автор: nornad 11.4.2007, 18:21
Цитата(Zamuta @  11.4.2007,  20:57 Найти цитируемый пост)
Как вам такое решение? 

Может и не сработать, имхо.
Цитата(Zamuta @  11.4.2007,  20:57 Найти цитируемый пост)
Вопрос в том чьими средствами это лучше сделать? В БД или коде? 

Сомневаюсь, что ты можешь сделать это средствами БД - тебе же всё равно надо писать в определённую таблицу. Ну, создал ты новую таблицу, хорошо. А как теперь будешь определять, в какую писать? По тому, что в первой уже 1000 записей, а во второй меньше? Хорошо. Заполнилась вторая, третья, пятидесятая таблица. Чуешь, как быстро начинает работать проверка того, куда писать?
Я для чего спрашивал, нафига оно тебе надо? Чтобы понть, где тебе лучше определять действия и таблицу, в которую писать.
Есть варианты:
  • на клиенте; это прокатит, если к базе обращается непосредственно клиент (структура клиент-сервер); в этом случае клиент сам определяет, заполнилась ли таблица, выполняет необходимые действия, сам как-то запоминает, с какой таблицей работать
  • на сервере; это подходит, если у тебя трёхзвенка; в этом случае сервер приложений определяет, что делать, когда делать и куда писать
Не зная твоей реально задачи, я не могу тебе сказать, что тебе подходит больше. Имхо, умнее делать трёхзвенку, т.к. точно не поимеешь проблем с кучей параллельных клиентов (ну, если всё правильно построишь ;)).

Автор: chief39 11.4.2007, 19:43
Чётко отвечая на твой вопрос:
Самое логичное что можно сделать строго по постановке задачи - это ставить лок на всю таблицу, делать селект каунт непосредственно перед вставкой и на основе его результатов уже вставлять/переключаться.

Но это будет очень однопоточно.....

Присоединяюсь к вопросу tux, Stampede, nornad - откуда такое требование и как оно звучит на более верхнем уровне абстракции?

Автор: Zamuta 11.4.2007, 20:29
Задача и правда не стандартная. Занимаюсь реализацией новой идеи, не то чтобы я боюсь, что идея будет реализована раньше меня, но бережёного сами знаете.... может я и параноик в этом смысле  smile . Так или иначе всю задачу я объяснить не могу, но если и объясню, то это никак не поможет решению задачи так как всё остальное это только идеалогия самого проекта по своей сути очень простого так же как и эта задача. При достижении N числа записей в таблице, запись в эту таблицу прекращается и выполняется команда select в этой таблице после чего об этом событии нужно оповестить некий метод в коде. Затем начинается запись в следующую таблицу, создаваемую автоматически, скажем так statement.executeUpdate("create table getCurrentTime()" ) и т.д. Первая таблица уже отправляется в архив и больше не трогается. В моём случае началом всей цепочки всех событий должен являться именно момент достижения количества записей в таблице равный N. Поэтому это очень ответственный момент.

Есть только 2 варианта. Это либо заранее смотреть сколько строк в бд и делать выводы либо пытаться записать и ловить эксепшн.
Почитав про триггеры в MySql (именно эта бд была выбрана), оказалось, что это не очень надёжная вещь и мне кажется не стоит ей пользоваться. 

Вообще нагрузка на бд в моём случае будет не критичной, только select, insert, update т.е. можно вообще создать отдельную бд именно для таких случаев. Поэтому пока остановлюсь на 
Цитата
это ставить лок на всю таблицу, делать селект каунт непосредственно перед вставкой и на основе его результатов уже вставлять/переключаться.


Хотя можно применить всё сразу и эксепшены ловить и триггеры ставить, так сказать страховать друг друга....

Автор: nornad 11.4.2007, 20:58
Может, лучше не создавать таблицу с именем по текущему времени, а просто переносить данные из таблицы в архив?
А по поводу того, как определять достижение предела... Тут нужно знать, локальная у тебя база или идёт общение по сети. Раз ты такой шпиён и параноик, то думай сам, как лучше сделать в конкретных условиях. Лично я бы просто делал определение количества записей в таблице перед добавлением новой. Потому как не представляю себе, какой эксепшн ты можешь ловить - базе по фигу, сколько твоя клиентская программа любит писать в таблицу и 1001 запись она добавит не ругаясь.

P.S. На будущее. Чем конкретнее опишешь ситуацию и возникшую проблему, тем проще будет помочь и более вероятна реальная помощь вместо пространных размышлений. А сейчас ситуация получилась такого плана: "Помогите мне решить проблему! - Что за проблема? - Этого я не могу сказать, но решить её надо.". Если всё так секретно, то спрашивать бесполезно - чтобы помогли, придётся рассказать довольно много. А если не боишься, что тебя опередят, то и незачем людей путать.  smile 

Автор: Zamuta 11.4.2007, 21:03
В любом случае спасибо....

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)