2 место Работа с MySql в многопотоке. Блокировка таблиц. Получение id добавленной записи.

не замечал глюки, на гетах и в 500 потоков
2018-12-22_020429.png
 
  • Спасибо
Реакции: DevOps, Lanidor и one
Может быть пора народу увидеть дбхелпер? Или хотя бы тем, кто сможет помочь в его доработке - выдать доступы? Думаю, @Karamzin приятно удивился бы уменьшению количества строк кода)
На самом деле не вижу смысла. Как уже отвечал тебе - большинству это не нужно, а кому нужно - тот либо сам напишет, либо готовую орм возьмет. Тем более это по факту даже не орм, а небольшая обертка для массового загона json данных в мускул + немного методов для удобства использования. Если кому-то прямо сильно интересно - пишите, дам доступ к проекту на гитлабе.
 
  • Спасибо
Реакции: Karamzin и Lord_Alfred
Здравствуйте. Вот если у меня два шаблона. Первый собирает данные в таблицу, а второй берет данные из этой таблицы. При блокировке таблицы эти шаблоны не будут перекрывать друг друга? Я так понял эта блокировка происходит как бы в самой базе данных и в таком режиме потоки смогут существовать. Или нет?
 
Здравствуйте. Вот если у меня два шаблона. Первый собирает данные в таблицу, а второй берет данные из этой таблицы. При блокировке таблицы эти шаблоны не будут перекрывать друг друга? Я так понял эта блокировка происходит как бы в самой базе данных и в таком режиме потоки смогут существовать. Или нет?
Будет работать само собой, лучше базу тогда innodb делать, что бы локов не ждать...
 
  • Спасибо
Реакции: Tsuk15
Будет работать само собой, лучше базу тогда innodb делать, что бы локов не ждать...
Спасибо за ответ! Столкнулся еще с одной проблемой: У меня есть две таблицы: Users и Users_del. Таблица Users_del выступает в роли черного списка, то есть, мне нужно взять первую строку из списка Users, удалить её и проверить есть ли такая строка в списке Users_del. Если такая строка есть, то берем следующую строку из списка Users. Повторяем это до тех пор, пока не возьмем строку, которой нет в черном списке. Я написал код для этого:
Код:
Развернуть Свернуть Копировать
Sql sqlConn = new Sql(project);
var cmd = sqlConn.Cmd();
cmd.Connection.Open();//открываем сессию
cmd.DbLock("Users WRITE, Users_del WRITE");//блокирую таблицу

object count = cmd.ExScalar("SELECT COUNT(*) FROM `Users`");
if(int.Parse(count.ToString())==0)
{
    cmd.DbUnLock();//разблокировка всех таблиц
    cmd.Connection.Close(); //закрываем сессию
    return "STOP"; //Если таблица пустая, то завршаю выполнение
}

do
{
    object user = cmd.ExScalar(@"SELECT `Users` FROM `Users` LIMIT 1"); //беру user
    cmd.ExNonQ("DELETE FROM Users LIMIT 1;"); //удаляю строку юзеры
    count = cmd.ExScalar("SELECT COUNT(*) FROM `Users`"); //обновляю count
    object del = cmd.ExScalar(@"SELECT Users_del FROM Users_del WHERE Users_del = "+user.ToString()+@";"); //проверяю наличия стоки в черном списке
    if(del!=null) continue; //если есть строка в чс, то берем следующую строку;
    cmd.DbUnLock();//разблокировка всех таблиц
    cmd.Connection.Close(); //закрываем сессию
    return Regex.Replace(user.ToString(),@"\W",""); //вывожу строку в переменную проекта
} while(int.Parse(count.ToString())>0);
    if(int.Parse(count.ToString())==0)
    {
        cmd.DbUnLock();//разблокировка всех таблиц
        cmd.Connection.Close(); //закрываем сессию
        return "STOP"; //Если строки закончились после проверок на чс
    }
Этот код адекватно работает в малопоточном режиме. Как только я наращиваю потоки хотя бы до 30, то ловлю ошибку: "Выполнение действия CSharp OwnCode Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding." В чем может быть проблема? Могу предположить, что мой код слишком перегружен и в нем есть какие-то нелогичные моменты. Сильно не ругайтесь, я до недавнего времени работал только со списками и пытаюсь применить какую-то "списочную" логику к базе данных. Возможно в этом и заключается ошибка. Буду очень благодарен за помощь!
 
У меня есть две таблицы: Users и Users_del. Таблица Users_del выступает в роли черного списка, то есть, мне нужно взять первую строку из списка Users, удалить её и проверить есть ли такая строка в списке Users_del. Если такая строка есть, то берем следующую строку из списка Users. Повторяем это до тех пор, пока не возьмем строку, которой нет в черном списке. Я написал код для этого:
Перед добавлением строки в Users можно сделать запрос на удаление всех юзеров из Users, которые есть в Users_del.
Приблизительно так:
Код:
Развернуть Свернуть Копировать
DELETE FROM Users WHERE Users in (SELECT Users_del FROM Users_del WHERE 1);
На столбцы Users и Users_del - добавить индексы (если их нет).
Перед тестированием запроса лучше сделать бэкап базы данных.
 
Этот код адекватно работает в малопоточном режиме. Как только я наращиваю потоки хотя бы до 30, то ловлю ошибку: "Выполнение действия CSharp OwnCode Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding." В чем может быть проблема? Могу предположить, что мой код слишком перегружен и в нем есть какие-то нелогичные моменты. Сильно не ругайтесь, я до недавнего времени работал только со списками и пытаюсь применить какую-то "списочную" логику к базе данных. Возможно в этом и заключается ошибка. Буду очень благодарен за помощь!
У тебя долго выполняются процессы. В результате по таймауту отваливаются соединения.
Добавь в общий код такую строчку:

где укажи сколько времени будет ждать свою очередь.
А вообще логику работы с БД надо делать совсем другую.
 
У тебя долго выполняются процессы. В результате по таймауту отваливаются соединения.
Добавь в общий код такую строчку:

где укажи сколько времени будет ждать свою очередь.
А вообще логику работы с БД надо делать совсем другую.
Совсем другую это какую?) Ну хотя бы в какую сторону думать
 
человек тебе даже ситрелками указал
 
что мне читать, ты к слову привязаться чтоль хотишь или не доволен что пример не дали рабочий на блюдечке ?
 
ещё скажи что ты слепой и без рукий )
 
ещё скажи что ты слепой и без рукий )
Автор показал мне как увеличить таймаут, за что ему спасибо, частично это решит проблему. Далее он указал на то, что моя логика в принципе не верна. Я решил задать ему вопрос по этому поводу (хотя я и изначально это предполагал). Ответит он или нет - это уже его дело. Мне всегда казалось, что в этом и есть смысл этого форума. У тебя лично я ничего не спрашивал
 
у него mysqk у тебя sql может тут логика скорости ?
не думаю что у тебя там работа с вложеными талицами
 
у него mysqk у тебя sql может тут логика скорости ?
не думаю что у тебя там работа с вложеными талицами
Может быть и так) таблицы там самые простейшие. В том то и дело, что я даже не понимаю в какую сторону думать и где черпать инфу. Я как привык работать со списками, так и тут пытаюсь
 
Может быть и так) таблицы там самые простейшие. В том то и дело, что я даже не понимаю в какую сторону думать и где черпать инфу. Я как привык работать со списками, так и тут пытаюсь
ну тут тебе только известно как построен шаблон, что он там делает, как, где то значит в шабе затык если всё просто и тормоз
 
Совсем другую это какую?) Ну хотя бы в какую сторону думать
В БД обычно удаление строк вообще не практикуется.
Ты с таблицами работаешь как со списками. Надо перестраиваться. Иначе смысла ни какого.
Принцип следующий:
У тебя должна быть одна таблица в которой есть дополнительная колонка status. И этот статус ты меняешь при необходимости. В твоем случае на del. И когда вытаскиваешь строку из таблицы указываешь что строка должна быть с колонкой status отличной от 'del'.
Если аккаунт в работе, то можешь присвоить статус например 'busy' или 'work'. Если закончил работу с ним, то меняй на 'done' 'complete'. Если нужно удалить, то на 'del'. Если акк забанен, то 'ban' и т.д.
Если нужно периодически перепроверять аккаунты раз в 2 часа, то добавляй колонку date и ставь туда время сейчас + 2 часа. Типа:
PHP:
Развернуть Свернуть Копировать
DateTime recheck_date = DateTime.UtcNow + new TimeSpan(0, 2, 0, 0);
var i = cmd.ExNonQ(@"UPDATE payout SET recheck_date='{0}' WHERE id={1};".f(recheck_date.ToString("yyyy-MM-dd HH:mm:ss"), pay[0]));
(в данном примере у меня вместо string.format сделано расширение .f())

а запрос на "не пора ли нам проверить":
PHP:
Развернуть Свернуть Копировать
DateTime date = DateTime.UtcNow;
var reader = cmd.ExReader(@"SELECT * FROM payout WHERE STATUS='request' AND (recheck_date<'{0}' OR recheck_date IS NULL) LIMIT 1;".f(date.ToString("yyyy-MM-dd HH:mm:ss")));
т.е. ищет запись с датой более ранней чем "сейчас"
 
  • Спасибо
Реакции: morgansho и Tsuk15
ну вообще так не используй SELECT * FROM не ищи по всем таблицам если знаешь конктректно в чём ищешь
 
В БД обычно удаление строк вообще не практикуется.
Ты с таблицами работаешь как со списками. Надо перестраиваться. Иначе смысла ни какого.
Принцип следующий:
У тебя должна быть одна таблица в которой есть дополнительная колонка status. И этот статус ты меняешь при необходимости. В твоем случае на del. И когда вытаскиваешь строку из таблицы указываешь что строка должна быть с колонкой status отличной от 'del'.
Если аккаунт в работе, то можешь присвоить статус например 'busy' или 'work'. Если закончил работу с ним, то меняй на 'done' 'complete'. Если нужно удалить, то на 'del'. Если акк забанен, то 'ban' и т.д.
Если нужно периодически перепроверять аккаунты раз в 2 часа, то добавляй колонку date и ставь туда время сейчас + 2 часа. Типа:
PHP:
Развернуть Свернуть Копировать
DateTime recheck_date = DateTime.UtcNow + new TimeSpan(0, 2, 0, 0);
var i = cmd.ExNonQ(@"UPDATE payout SET recheck_date='{0}' WHERE id={1};".f(recheck_date.ToString("yyyy-MM-dd HH:mm:ss"), pay[0]));
(в данном примере у меня вместо string.format сделано расширение .f())

а запрос на "не пора ли нам проверить":
PHP:
Развернуть Свернуть Копировать
DateTime date = DateTime.UtcNow;
var reader = cmd.ExReader(@"SELECT * FROM payout WHERE STATUS='request' AND (recheck_date<'{0}' OR recheck_date IS NULL) LIMIT 1;".f(date.ToString("yyyy-MM-dd HH:mm:ss")));
т.е. ищет запись с датой более ранней чем "сейчас"
ну вообще так не используй SELECT * FROM не ищи по всем таблицам если знаешь конктректно в чём ищешь
Вот спасибо :ay: вроде суть уловил, попробую применить
 
Вот спасибо :ay: вроде суть уловил, попробую применить
Размер базы какой?
Индексы есть (ооооооочень сильно ускоряет)?
По хорошему надо делать left join с таблицей которая в бане, а к стате если в бане вы выясняете по ходу пьесы - вам верно сказали проще поле (статус) добавить что был бан и апдейт делать...
 
Размер базы какой?
Индексы есть (ооооооочень сильно ускоряет)?
По хорошему надо делать left join с таблицей которая в бане, а к стате если в бане вы выясняете по ходу пьесы - вам верно сказали проще поле (статус) добавить что был бан и апдейт делать...
Индекс это id? Если да, то есть, если нет, то перед тем как это писать не гуглил даже. Немного освобожусь, вникну более детально и попробую применить все рекомендации
 
Индекс это id? Если да, то есть, если нет, то перед тем как это писать не гуглил даже. Немного освобожусь, вникну более детально и попробую применить все рекомендации
ищи в гугле индексирование таблиц mysql
также изучи курс, который я рекомендовал ранее https://geekbrains.ru/courses/86 можешь поискать на торрентах. там как раз узнаешь про объединение таблиц
 
  • Спасибо
Реакции: Tsuk15
id само собой примари индекс у тебя должен быть... после бана/удаления и других смен статусов по этому id и нужен апдейт
На поле статус тоже нужен index - тогда условно если ты будешь делать select * from users where status='active' limit 1; у тебя выборка пойдёт только по "живим" узерам, а не по всем подряд... - значительно ускорит процесс
Грубо индексы нужны на те поля по которым ты делаешь выборки/сортировки т.е. то что ты пишешь после where или ордер бай
 
  • Спасибо
Реакции: Tsuk15
Грубо индексы нужны на те поля по которым ты делаешь выборки/сортировки т.е. то что ты пишешь после where или ордер бай
Тоже переношу все в бд.
Чаще всего делаю выборки по 'status' и 'timestamp' то есть нужно делать индексы на все параметры?
Особенно интересует, нужен ли индекс для timestamp или он как primary key индексируется автоматически?
И не навредит ли большое количество индексов в каждой таблице? У меня это как минимум получается 4 индекса на одну таблицу (id, login, status, timestamp)
 
И не навредит ли большое количество индексов в каждой таблице?
Навредит. Из-за индексов увеличивается время вставки/удаления из таблицы. Чем больше индексов - тем дольше будет вставлять новую строчку (т.к. обрабатывает индекс каждую вставку).
На мелких базах это будет незаметно, но когда данных будет много - вы почувствуете, что явно что-то тормозит))
Поэтому индексы нужно создавать с умом. Это целая наука и тут вряд ли кто-то точно скажет как быть, в идеальном мире нужно анализировать запросы в базе с индексами и без индексов, но мало кто так делает.
Поэтому просто не перебарщивайте с количеством индексов и делайте только те, которые нужны. И не дублируйте индексы (речь о индексе из нескольких полей).
 
  • Спасибо
Реакции: ZSharp

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)