Помогите решить задачу.

Buldozer

Новичок
Помогите решить задачу.

Есть задача, реализовать некий шейпер, который бы ограничил кол-во конектов к одному сайту.
итого есть две таблицы:
PHP:
mysql> describe spider_check_query;
+----------------+---------------------+------+-----+---------+-------+
| Field          | Type                | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------+-------+
| page_id        | int(10) unsigned    | NO   | PRI |         |       |
| page_url       | char(255)           | NO   |     |         |       |
| site_id        | int(10) unsigned    | NO   | MUL |         |       |
| site_url       | char(255)           | NO   |     |         |       |
| link           | char(255)           | NO   |     |         |       |
| initiated_date | int(10) unsigned    | NO   | MUL | 0       |       |
| status         | tinyint(3) unsigned | NO   | MUL | 0       |       |
| result         | tinyint(3) unsigned | NO   | MUL | 0       |       |
+----------------+---------------------+------+-----+---------+-------+

mysql> describe spider_checker_limiter;
+---------+------------------+------+-----+---------+-------+
| Field   | Type             | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| site_id | int(10) unsigned | NO   | PRI |         |       |
| count   | int(11)          | NO   |     |         |       |
+---------+------------------+------+-----+---------+-------+
в первой хранится инфомация для обработки, вторая реализует этот самый шейпер.
алгоритм такой:
PHP:
1. делаем выборку из таблиц исключая те записи, которые принадлежат сайтам привысившим лимит соединений(т.е. select page_id, page_url, site_id, site_url, link from spider_check_query where status = 0 and site_id not in (select site_id from spider_checker_limiter where count >= 2) limit 1)
2. повышаем счетчик соединений для данного сайта("INSERT INTO spider_checker_limiter values('$site_id', '1') ON DUPLICATE KEY UPDATE count = count + 1"), что бы соблюсти необходимый лимит + помечаем запись как обрабатываемую("mysql_query("update spider_check_query set status = 1, initiated_date = $timestamp where page_id = $page_id");
")
3. обрабатываем данные.
4. по завершению работы минусуем счетчик соединений для сайта, и помечаем запись как обработанную.
*задумка шейпера - что если запись и сайт будут помечаны как используемые, то эта запись и записи принадлежащие этому сайту не будут выбираться больше указанного лимита.
*проблема шейпера - что между селектом и апдэйтом/инсертом(который помечает, записи как используемые) параллельно выполняемые копии скрипта успевают сделать еще несколько селектов и в результате ограничение не соблюдается, и более того одна и та же запись обрабатывается в несколько потоков.
*решено было использованием блокировки - т.е. с пункта 1 по 2 таблицы блокируются и соответственно ограничение теперь соблюдается, но…
*новая проблема - база практически висит из-за постоянных блокировок, сменил тип таблицы на memory, но это не очень помогло.

Как вариант: использовать блокировку физического файла… но скрипты могут запускаться с разных серверов =>… не получится.

Еще вариант: с использованием некой служебной таблицы, которая состоит из одной единственной ячейки, которая может содержать или 1 или 0. 1 – значит, что сейчас производится операция выборки данных для шейпера, и данные выбирать нельзя; 0 – значит, что операции выборки сейчас не производится и следовательно можно выбирать…
PHP:
1.	ожидаем как только флаг будет = 0
2.	как только флаг = 0, лочим таблицу и выставляем флаг 1
3.	делаем unlock(что бы иметь возможность работать с другими таблицами)
4.	делаем выборку согласно ограничениям
5.	выставляем флаг 0
6.	обрабатываем данные
здесь смущает первый пункт… придется постоянно опрашивать таблицу, в то время, как на данный момент, скрипт просто посылает запрос и ждет когда его мускуль обслужит.
 
Сверху