powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Объясните про транзакции
10 сообщений из 10, страница 1 из 1
Объясните про транзакции
    #39341597
dart_sitius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть такие запросы (делаю через php):
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE `tbl` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `data` varchar(100) NOT NULL,
  `hash` varchar(10) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `knock` (`knock`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
$hash = sanitize($_GET['hash']);
$res = $mysqli->query("SELECT `id`, `data` FROM `$sql_table` WHERE `knock`< NOW() - INTERVAL 300 SECOND LIMIT 100");
$ids = array();
if ($res) {
    while ($row = $res->fetch_row()) {
        echo implode(" ", $row)."\n";
        $ids[] = $row[0];
    }
    $res->free();
}
if (isset($ids) && count($ids) != 0) {
    $mysqli->query("UPDATE `$sql_table` SET `knock`=NOW(), `hash`='$hash' WHERE `id` IN ('".implode("','", $ids)."')");
}


На php скрипт идет по 5 запросов в секунду. Очевидно, что происходят коллизии, т.е 2 разным пользователям select выдает пересекающиеся строки, затем в UPDATE хеш второго пользователя затирает первого, и первый делает лишнюю работу (так как при не совпадении хеша в дальнейшем результат откинется).
Вот такой велосипед. Подскажите, как сделать по-нормальному?
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341610
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dart_sitius,


Код: sql
1.
2.
3.
UPDATE `$sql_table`
SET `knock`=NOW(), `hash`='$hash'
WHERE `id` IN (SELECT `id` FROM `$sql_table` WHERE `knock`< NOW() - INTERVAL 300 SECOND LIMIT 100)


Только учтите, что LIMIT без ORDER BY - рулетка.
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341613
dart_sitius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, спасибо. Только мне еще данные из SELECT нужно вывести на экран.
Насчет order by - не страшно, что рулетка, главное, чтобы быстро работало.
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341615
dart_sitius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, Думаю, может сменить myisam на innodb и к SELECT просто в конце добавить FOR UPDATE ? Тогда вроде бы это будет единой транзакцией, сильно ли замедлится работа?
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341616
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм, нет, не так. Не обратил внимание, что таблица одна и та же.
Тогда так:
Код: sql
1.
2.
3.
UPDATE `$sql_table`
SET `knock`=NOW(), `hash`='$hash'
WHERE `knock`< NOW() - INTERVAL 300 SECOND LIMIT 100


А вывести потом можно с помощью этого:
Код: sql
1.
SELECT `id`, `data` FROM `$sql_table` WHERE `hash`='$hash'
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341617
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dart_sitiusДумаю, может сменить myisam на innodbЕсли у вас сейчас MyISAM, то никаких транзакций у вас нет, он их не поддерживает.
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341619
dart_sitius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, вывод по hash не подходит, потому что в таблице очень много строк с одинаковыми хешами. Мне нужно вывести только те строки, которые выданы в данной транзакции, т.е только эти айдишники
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341623
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dart_sitiusМне нужно вывести только те строки, которые выданы в данной транзакции, т.е только эти айдишникиТогда остается только ваш изначальный вариант.
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341627
dart_sitius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoft, ну а если изменить на innodb? как будет выглядеть вариант с транзакциями?
Мне нужно что-то типа критической секции, желательно построчно (чтобы быстрее работало).
Идеально было бы, если бы первый пользователь сделал SELECT, и эти строки "скрылись" от других пользователей, пока не будет сделан update.
А другие пользователи тем временем не ждали, а просто получили в SELECT другие строки. Такое возможно?
...
Рейтинг: 0 / 0
Объясните про транзакции
    #39341632
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dart_sitius,

Можно, если добавить поле-метку текущей "партии" (или сессии).
"Захват":
Код: sql
1.
2.
3.
UPDATE `$sql_table`
SET `knock`=NOW(), `hash`='$hash', current_session=CONNECTION_ID()
WHERE `knock`< NOW() - INTERVAL 300 SECOND LIMIT 100

(CONNECTION_ID() - плохой вариант, т.к. уникальность гарантируется только для каждого отдельно взятого момента времени, но не в интервале времени)

Выборка остальных полей:
Код: sql
1.
SELECT `id`, `data` FROM `$sql_table` WHERE current_session=CONNECTION_ID()


"Освобождение":
Код: sql
1.
UPDATE `$sql_table` SET current_session=NULL WHERE current_session=CONNECTION_ID()


Будет нужен индекс по полю current_session.

И нужно предусмотреть механизм "освобождения" записей досрочно умершими сессиями.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Объясните про транзакции
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]