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

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
не замечал глюки, на гетах и в 500 потоков
2018-12-22_020429.png
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
824
Баллы
93
  • Спасибо
Реакции: DevOps, Lanidor и one

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113

DmitryAk

Client
Регистрация
14.12.2016
Сообщения
860
Благодарностей
824
Баллы
93
Может быть пора народу увидеть дбхелпер? Или хотя бы тем, кто сможет помочь в его доработке - выдать доступы? Думаю, @Karamzin приятно удивился бы уменьшению количества строк кода)
На самом деле не вижу смысла. Как уже отвечал тебе - большинству это не нужно, а кому нужно - тот либо сам напишет, либо готовую орм возьмет. Тем более это по факту даже не орм, а небольшая обертка для массового загона json данных в мускул + немного методов для удобства использования. Если кому-то прямо сильно интересно - пишите, дам доступ к проекту на гитлабе.
 
  • Спасибо
Реакции: Karamzin и Lord_Alfred

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
Здравствуйте. Вот если у меня два шаблона. Первый собирает данные в таблицу, а второй берет данные из этой таблицы. При блокировке таблицы эти шаблоны не будут перекрывать друг друга? Я так понял эта блокировка происходит как бы в самой базе данных и в таком режиме потоки смогут существовать. Или нет?
 

Gfoblin

Client
Регистрация
30.05.2013
Сообщения
4 596
Благодарностей
1 014
Баллы
113
Здравствуйте. Вот если у меня два шаблона. Первый собирает данные в таблицу, а второй берет данные из этой таблицы. При блокировке таблицы эти шаблоны не будут перекрывать друг друга? Я так понял эта блокировка происходит как бы в самой базе данных и в таком режиме потоки смогут существовать. Или нет?
Будет работать само собой, лучше базу тогда innodb делать, что бы локов не ждать...
 
  • Спасибо
Реакции: Tsuk15

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
Будет работать само собой, лучше базу тогда 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." В чем может быть проблема? Могу предположить, что мой код слишком перегружен и в нем есть какие-то нелогичные моменты. Сильно не ругайтесь, я до недавнего времени работал только со списками и пытаюсь применить какую-то "списочную" логику к базе данных. Возможно в этом и заключается ошибка. Буду очень благодарен за помощь!
 

Alex733

Client
Регистрация
27.11.2017
Сообщения
330
Благодарностей
243
Баллы
43
У меня есть две таблицы: 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 - добавить индексы (если их нет).
Перед тестированием запроса лучше сделать бэкап базы данных.
 

Karamzin

Client
Регистрация
24.05.2016
Сообщения
214
Благодарностей
432
Баллы
63
Этот код адекватно работает в малопоточном режиме. Как только я наращиваю потоки хотя бы до 30, то ловлю ошибку: "Выполнение действия CSharp OwnCode Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding." В чем может быть проблема? Могу предположить, что мой код слишком перегружен и в нем есть какие-то нелогичные моменты. Сильно не ругайтесь, я до недавнего времени работал только со списками и пытаюсь применить какую-то "списочную" логику к базе данных. Возможно в этом и заключается ошибка. Буду очень благодарен за помощь!
У тебя долго выполняются процессы. В результате по таймауту отваливаются соединения.
Добавь в общий код такую строчку:

где укажи сколько времени будет ждать свою очередь.
А вообще логику работы с БД надо делать совсем другую.
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
У тебя долго выполняются процессы. В результате по таймауту отваливаются соединения.
Добавь в общий код такую строчку:

где укажи сколько времени будет ждать свою очередь.
А вообще логику работы с БД надо делать совсем другую.
Совсем другую это какую?) Ну хотя бы в какую сторону думать
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
человек тебе даже ситрелками указал
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
что мне читать, ты к слову привязаться чтоль хотишь или не доволен что пример не дали рабочий на блюдечке ?
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
ещё скажи что ты слепой и без рукий )
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
ещё скажи что ты слепой и без рукий )
Автор показал мне как увеличить таймаут, за что ему спасибо, частично это решит проблему. Далее он указал на то, что моя логика в принципе не верна. Я решил задать ему вопрос по этому поводу (хотя я и изначально это предполагал). Ответит он или нет - это уже его дело. Мне всегда казалось, что в этом и есть смысл этого форума. У тебя лично я ничего не спрашивал
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
у него mysqk у тебя sql может тут логика скорости ?
не думаю что у тебя там работа с вложеными талицами
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
у него mysqk у тебя sql может тут логика скорости ?
не думаю что у тебя там работа с вложеными талицами
Может быть и так) таблицы там самые простейшие. В том то и дело, что я даже не понимаю в какую сторону думать и где черпать инфу. Я как привык работать со списками, так и тут пытаюсь
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
Может быть и так) таблицы там самые простейшие. В том то и дело, что я даже не понимаю в какую сторону думать и где черпать инфу. Я как привык работать со списками, так и тут пытаюсь
ну тут тебе только известно как построен шаблон, что он там делает, как, где то значит в шабе затык если всё просто и тормоз
 

Karamzin

Client
Регистрация
24.05.2016
Сообщения
214
Благодарностей
432
Баллы
63
Совсем другую это какую?) Ну хотя бы в какую сторону думать
В БД обычно удаление строк вообще не практикуется.
Ты с таблицами работаешь как со списками. Надо перестраиваться. Иначе смысла ни какого.
Принцип следующий:
У тебя должна быть одна таблица в которой есть дополнительная колонка 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

Karamzin

Client
Регистрация
24.05.2016
Сообщения
214
Благодарностей
432
Баллы
63

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 041
Баллы
113
ну вообще так не используй SELECT * FROM не ищи по всем таблицам если знаешь конктректно в чём ищешь
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
В БД обычно удаление строк вообще не практикуется.
Ты с таблицами работаешь как со списками. Надо перестраиваться. Иначе смысла ни какого.
Принцип следующий:
У тебя должна быть одна таблица в которой есть дополнительная колонка 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: вроде суть уловил, попробую применить
 

Gfoblin

Client
Регистрация
30.05.2013
Сообщения
4 596
Благодарностей
1 014
Баллы
113
Вот спасибо :ay: вроде суть уловил, попробую применить
Размер базы какой?
Индексы есть (ооооооочень сильно ускоряет)?
По хорошему надо делать left join с таблицей которая в бане, а к стате если в бане вы выясняете по ходу пьесы - вам верно сказали проще поле (статус) добавить что был бан и апдейт делать...
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28
Размер базы какой?
Индексы есть (ооооооочень сильно ускоряет)?
По хорошему надо делать left join с таблицей которая в бане, а к стате если в бане вы выясняете по ходу пьесы - вам верно сказали проще поле (статус) добавить что был бан и апдейт делать...
Индекс это id? Если да, то есть, если нет, то перед тем как это писать не гуглил даже. Немного освобожусь, вникну более детально и попробую применить все рекомендации
 

Tsuk15

Client
Регистрация
25.04.2017
Сообщения
102
Благодарностей
40
Баллы
28

Karamzin

Client
Регистрация
24.05.2016
Сообщения
214
Благодарностей
432
Баллы
63
Индекс это id? Если да, то есть, если нет, то перед тем как это писать не гуглил даже. Немного освобожусь, вникну более детально и попробую применить все рекомендации
ищи в гугле индексирование таблиц mysql
также изучи курс, который я рекомендовал ранее https://geekbrains.ru/courses/86 можешь поискать на торрентах. там как раз узнаешь про объединение таблиц
 
  • Спасибо
Реакции: Tsuk15

Gfoblin

Client
Регистрация
30.05.2013
Сообщения
4 596
Благодарностей
1 014
Баллы
113
id само собой примари индекс у тебя должен быть... после бана/удаления и других смен статусов по этому id и нужен апдейт
На поле статус тоже нужен index - тогда условно если ты будешь делать select * from users where status='active' limit 1; у тебя выборка пойдёт только по "живим" узерам, а не по всем подряд... - значительно ускорит процесс
Грубо индексы нужны на те поля по которым ты делаешь выборки/сортировки т.е. то что ты пишешь после where или ордер бай
 
  • Спасибо
Реакции: Tsuk15

ZSharp

Client
Регистрация
29.09.2013
Сообщения
395
Благодарностей
126
Баллы
43
Грубо индексы нужны на те поля по которым ты делаешь выборки/сортировки т.е. то что ты пишешь после where или ордер бай
Тоже переношу все в бд.
Чаще всего делаю выборки по 'status' и 'timestamp' то есть нужно делать индексы на все параметры?
Особенно интересует, нужен ли индекс для timestamp или он как primary key индексируется автоматически?
И не навредит ли большое количество индексов в каждой таблице? У меня это как минимум получается 4 индекса на одну таблицу (id, login, status, timestamp)
 

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
И не навредит ли большое количество индексов в каждой таблице?
Навредит. Из-за индексов увеличивается время вставки/удаления из таблицы. Чем больше индексов - тем дольше будет вставлять новую строчку (т.к. обрабатывает индекс каждую вставку).
На мелких базах это будет незаметно, но когда данных будет много - вы почувствуете, что явно что-то тормозит))
Поэтому индексы нужно создавать с умом. Это целая наука и тут вряд ли кто-то точно скажет как быть, в идеальном мире нужно анализировать запросы в базе с индексами и без индексов, но мало кто так делает.
Поэтому просто не перебарщивайте с количеством индексов и делайте только те, которые нужны. И не дублируйте индексы (речь о индексе из нескольких полей).
 
  • Спасибо
Реакции: ZSharp

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