--}}
Новая тема
Вы не можете создавать новые темы.
Т.к. вы неавторизованы на сайте. Пожалуйста назовите себя или зарегистрируйтесь.
Список тем

Mysql INSERT IGNORE auto-increment holes

Серьёзная тема
600
22
С друзьями на NN.RU
В социальных сетях
Поделиться
Qavai
20 февраля в 12:47
Оказывается, интересные вещи есть, я только спустя 16 лет практики наткнулся на этот баг =)

Вот думаю, как обойти это.

Вы как справляетесь с этим?
DimN
21 февраля в 17:04
А почему это баг и зачем с ним справляться?
Qavai
21 февраля в 18:45
это даже не баг, а фича, неприятная, если не знать о ней.

решение простое с виду

"INSERT INTO `table`(#fields#)
SELECT #values# FROM dual WHERE NOT EXISTS(
SELECT NULL FROM `table` WHERE `title`=#values#
DimN
21 февраля в 19:40
Это фича совершенно всех СУБД (ну, возможно, существуют и другие, но я не хочу о них даже слышать), как можно об этом не знать? Любая неудачная попытка вставки всё равно сдвигает автоинкрементный счетчик, это нормально, если мы не хотим иметь геморрой с блокировками в многопользовательских приложениях.

И второй вопрос: зачем бороться с дырами? Они неизбежны при любых извращениях. Например, они появятся при rollback или просто при банальном delete. И даже попытка защититься при помощи not exists не сработает, если не повысить уровень изоляции транзакции со стандартного read committed, потому что иначе между проверкой и вставкой кто-то может влезть, хоть и с очень небольшой вероятностью, конечно.

Нельзя суррогат использовать в бизнес-логике. Если прям требуется какая-то непрерывная нумерация, скажем, документов (хотя обычно достаточно уникальности и иногда возрастания, причем, нередко со сбросом номера в ноль с наступлением нового года), писать честную нумерацию с блокировками и мириться с дополнительными расходами.
Qavai
21 февраля в 23:37
ну при чём тут сразу многопользовательское?

у меня вот просто таблица с тегами.
и я её наполняю.
один юзер. больше никого нет

и я просто не хочу чтобы были дыры, а чтобы было всё последовательно через 1.

так просто удобнее и симпатишнее, чем если, например, 5000 слов, а последний id будет равен какому-нибудь 35000, а не 5000

и через вот этот запрос это работает.
но, конечно, можно сделать и по другому, сложнее, но зачем?

в моей задаче этого не требуется
DimN
22 февраля в 00:33
Не, ну дело хозяйское, если так уж хочется :о) Но если вставляет один юзер, скорее всего, дублей будет считаные единицы и id будет 5010, например. Хотя, на мой вкус, и 35000 ничем не плохо.

А если в транзакции, кроме вставки в эту таблицу, есть еще какие-то действия, которые вызовут ошибку и приведут к откату транзакции, всё равно получите дырку :о)
Qavai
22 февраля в 13:43
да я тут небольшую задачку реализовал

есть вакансии на хабре https://career.habr.com/vacancies/rss...

это rss

я проверяю каждые 15 минут и заношу их в базу данных
там список 50 шт
там у каждой вакансии есть Требуемые навыки, это теги

// Требуемые навыки: #senior, #Java, #Kotlin, #PostgreSQL, #MySQL, #ApacheKafka, #RabbitMQ, #Kubernetes, #Docker, #SpringBoot.

эти теги я заношу в другую таблицу как уникальные, каждому теги делаю id
чтобы потом их связать с вакансиями через id
ну например, вывести список наиболее нужных тегов (умений), которые требуются
и т.п.

так вот, к теме
около 150 тегов каждые 15 минут заносятся в таблицу
и вот когда через час я увидел список тегов в количестве 900, а id в районе 3000, ну это просто не очень хорошо
и оно будет продолжать увеличиваться, дыр просто очень много. по экспоненте идут.

никаких многопользователей тут нет, транзакций и т.п. нет, всё в один поток
DimN
23 февраля в 10:32
Ну в целом понятно... В общем случае проверка существования записи кошернее, чем вставка с игнором ошибки, и дело даже не в дырках автоинкремента, а в том, что ошибку нужно поймать и обработать, иначе с логикой работы приложения могут быть проблемы.

Вот рассмотрим ваш случай. Я так понял, есть три таблицы: Т1 -- справочник тегов, в который заносятся уникальные значения этих тегов, Т2 -- таблица вакансий, Т3 -- таблица для хранения связи между ID вакансии и ID тегов, которые в этой вакансии упоминаются. Судя по всему, алгоритм примерно такой: сначала вакансия разбирается один раз для сохранения новых тегов в Т1, а потом еще раз пробегаем по всем тегам вакансии, находим их ID в Т1 и заполняем Т3. Двойная работа. Обычно делается так: пробегаем по тегам вакансии и ищем каждый тег в Т1.
1) если находим, то найденный ID тега сохраняем в Т3,
2) если не находим, то вставляем запись в Т1, получаем ID тега не поиском(!), а средствами СУБД, каждая из них умеет возвращать значение последнего вставленного автоинкремента (беглое гугление говорит, что для MySQL это last_inser_id(), может и другие функции есть). Полученный ID также сохраняем в Т3.

И вот в случае игнора ошибки вы лишаетесь возможности использовать средство СУБД и вынуждены два раза искать тег в справочнике: сначала при вставке, потом для сохранения связи.

Но, конечно, для игрушечной задачи всё это не имеет никакого значения :о)
Qavai
23 февраля в 16:12
вероятно, так и сделаю, просто позже.

просто пока не стал делать таблицу связей, поэтому id и не нужен.

обычно в реальном проекте я не пользуюсь ignore, здесь просто так было проще сделать, одним запросом в бд
Qavai
4 марта в 09:21
сделал вывод списка e-ivanov.ru/projects/careerhabrcom-own-filters/live/

это список вакансий, которые не-поднятые, то есть, совершенно новые.

как видно, намного меньше стало мишуры

скоро добавлю фильтры тагов
DimN
9 марта в 09:17
Пэйджинг надо поправить, первая страница выдачи должна иметь номер 1, а не 76 :о)
Qavai
9 марта в 10:49
нет.
первая страница - она и есть первая, там первые записи идут.
а 76 - это самые последние записи

это обратный страничник, моё изобретение

если данные из списка не удаляются (а это на 100% так), то на 60 странице https://e-ivanov.ru/projects/careerha... , например, мы ВСЕГДА будем находить одни и те же записи, те сверху будет всегда "Требуется Full-stack middle-middle+ программист (YII2, VUE) (Кострома)", сколько бы записей не добавилось новых, те, даже когда будет всего 120 или 1200 страниц.

а если делать прямой страничник (который неправилен для временнЫх записей), то на 60 странице после добавления новых записей будет постоянно сдвигаться записи и мы через месяц или год не найдём на 60 странице ту запись, которую там видели.
DimN
9 марта в 12:56
А зачем нам, чтобы какая-то древняя запись всегда лежала на одной и той же странице (тем более что эта страница сохранится только при поиске по тем же критериям)? ИМХО, это странное желание из того же разряда, что и отсутствие дыр в автоинкременте :о) То есть через год я буду помнить, что при поиске вакансии по ключевым словам "MySQL", "PHP", "зарплата от 300 000" что-то интересное было на 60-й странице? Если мне интересна конкретная вакансия, я сохраню прямую ссылку на нее (хоть эта вакансия и протухнет в скором времени).

И, кстати, надо определиться, это архив, из которого ничего не удаляется, или это живая база действующих вакансий, тогда устаревший мусор при выдаче не нужен и никакие номера страниц не сохранятся.

Ну, если так и задумано, то ОК, я ж ТЗ не читал, думал, баг :о)
diper
11 марта в 10:42
Большие компании напрямую с hh не работают, а используют какую-нидь прокладку для автоматизации процесса HR, в том числе для бампа вакансий по расписанию.

Искать вакансии "алмазы"... лучше будь сам алмазом чтоб тебя искали)
Qavai
11 марта в 11:31
не находят.

надо самому искать и пробиваться, потому что им тупо "лень" искать.



история:



я вот недавно в декабре случайно нашёл пару интересных вакансий на хабркарьере, да и то где-то на 10 странице, долго прокручивал и отсеивал мишуру.



пособеседовался, в одну шаражку взяли, дали 120 на испытательный, потом 140



но я туда не пошёл, потому что они не ответили на 5...10 простых вопросов (про отпуска и т.п.), хрюша сказала "мне тупо лень отвечать"

типа давай работай



а потом глянул их вакансии на хх, там мастер рабочий без опыта - 90, с опытом 120. гибкие окна делать.



вот так вот.

поэтому вот и занялся этим проектом, чтобы не тратить время на поиск нужных мне вакансий. на самом сайте уж неудобные фильтры, да и нет rss для них
DimN
11 марта в 12:37
Qavai писал(а)
пособеседовался, в одну шаражку взяли, дали 120 на испытательный, потом 140
...
а потом глянул их вакансии на хх, там мастер рабочий без опыта - 90, с опытом 120. гибкие окна делать.
Ну это понятно, есть куча фирм, где айтишное подразделение -- необходимое зло, не приносящее денег, а только их потребляющее. Соответственно, отношение к таким обслуживающим структурам не самое позитивное. Лучше стремиться работать в фирмах, для которых ИТ -- основная деятельность.

Раньше к таким бизнесам, где ИТ -- обслуга, относились и банки, но сейчас многие из них при помощи ИТ зарабатывают больше, чем при помощи маринок в отделениях и разного рода кредитных менеджеров. Плюс ИТ выделяют в обособленные структуры со своим руководством, имеющим вес в общей иерархии, что способствует повышению статуса айтишников. То есть работа в ИТ-структурах банков стала мало чем отличаться от работы в обычных девелоперских фирмах.
Qavai
11 марта в 22:34
наконец-то доделал фильтры по тегам.

проставил на каждый тег по весу. от -100 до 100 можно ставить
проставил на ненужные мне теги -100, и вот сразу стало 155 вакансий, а всего их 2100
крысота!
пофиксил rss, теперь там всё хорошо
но 155 - это для меня только, когда я авторизован.

остальные продолжают видеть без фильтров. там сейчас 833 шт
но тоже неплохо, остальные 1300 мишура скрыты

пользуйтесь

запрос такой набросал, работает быстро

INNER JOIN (
SELECT i4t.guid, MIN(t.cost) AS min_cost, t.title AS tag_title FROM `habr_career_tags` AS t
INNER JOIN `habr_career_item4tag` AS i4t
ON (
i4t.tag_id = t.id
)
WHERE 1
GROUP BY guid
HAVING min_cost >= 0
) AS pt ON (
pt.guid = p.guid
)

позже может быть сделаю на странице форму с выбором тегов, которые нужно игнорировать
пока есть другой проект
Atom
21 февраля в 20:57
Почему баг-то? )
diper
1 марта в 23:44
а вариант по первой ссылке со stackoverflow чем не вариант?
Qavai
5 марта в 11:08
там полно вариантов
Саламан
8 марта в 00:04
auto-increment id - это техническое поле оно может иметь абсолютно любое значение.
оно нужно только для удобной связи между таблицами.
По сути вы вообще не должны на него полагаться, поскольку auto-increment id могут изменяться в ходе восстановления или копирования данных или прочих админских работ.
Qavai
8 марта в 17:24
уже накопилось 2000 вакансий

вот такая раскладка по умениям (тегам), самым популярным:

e-ivanov.ru/p/2403/8d.png
Новая тема
Вы не можете создавать новые темы.
Т.к. вы неавторизованы на сайте. Пожалуйста назовите себя или зарегистрируйтесь.
Список тем
Последние темы форумов
Соль поваренная пищевая 5кг 1кг помол 1

Цена в руб./кг в зависимости от...(!) Самосадочная ГОСТ Р 51574-2003 Сорт первый Фасовка: • полиэтиленовый пакет 1000 г •...
Цена: 17 руб.

Формы для дорожных плит П30.18

Формы для дорожных плит П30.18 Оборудование для производства дорожных плит. Дорожные плиты - железобетонные изделия, применяемые для...
Цена: 162 000 руб.

Восстановление отверстий спецтехники

Услуга мобильного наплавочно-расточного комплекса по восстановлению, ремонту отверстий на спецтехнике и промышленном...
Цена: 10 000 руб.

Банковский счет в ОАЭ под ключ

Здравствуйте! Меня зовут Александра, и я помогу открыть Вам банковский счет в ОАЭ. Все услуги выполняю "под ключ". Гарантирую...

Программист-разработчик Full-Stack ГК "Kolobox"
70000 -
100000 руб.
Высшее образование, стаж работы более 5 лет, полная занятость
Разработчик .net Profit Search
70000 -
100000 руб.
Неполное среднее образование, стаж работы 3-5 лет, полная занятость
Frontend-разработчик Profit Search
40000 -
50000 руб.
Стаж работы 3-5 лет, частичная занятость
Программист 1С НПП ПРО-М
от 110 000 руб.
Высшее образование, стаж работы 3-5 лет, полная занятость