powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Многоуровневая блокировка/синхронизация потоков
19 сообщений из 44, страница 2 из 2
Многоуровневая блокировка/синхронизация потоков
    #39489122
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdevСкажем так: под некоторые "справочники" будут создаться отдельные таблицы и удаляться при удалении справочника.
Для этого используются временные таблицы.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489139
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторПри работе с базой данных тип используемого инструмента для блокировок не имеет никакого значения. Все разница в быстродействии исчезнет на фоне работы с данными

Ну смотрите, допустим нужно прочитать 3 миллиона записей из таблицы чтобы составить некий сводный отчет. Если мы используем CriticalSection - все остальные клиенты не смогут ни читать, ни писать пока идет чтение данных. А в случае MREW - остальные смогут читать и только некоторые не смогут писать. Поскольку запись у нас реже чтения - это критично.

авторТак может просто потоки неправильно настроены? Для SQLite каждый поток должен иметь свое собственное соединение с базой и с включенной опцией мультитрединг.

Тут все правильно. Сама дллка собрана с опцией мультитрединг и какждый поток создает свое подключение к базе. Но ограничение на один пишущий поток и на модификацию sqlite_master - это описано в доках sqlite и это (конкретно в нашем случае) нужно разруливать.

авторДля этого используются временные таблицы.

Насколько я понял из доков Sqlite - временные таблицы удаляются когда закрывается последнее соединение к базе. Т.е. при перезапуске сервера временные таблицы потеряются.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489144
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdev, я в общем понял, в чем основная проблема... Вам нужен толковый архитектор.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489145
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdevавторно ведь ты собрался активно выполнять "сreate table/drop table", что мне совсем не нравится.

Не активно, нет ! Изредка. Скажем так: под некоторые "справочники" будут создаться отдельные таблицы и удаляться при удалении справочника. Это будет происходить редко - раз в день, а может и раз в месяц. Тем не менее это иногда будет происходить. Когда это происходит - нужно полностью блокировать базу на чтение/запись из других потоков (а по сути - другими клиентами сервера).

Как это сделать ? Либо написать свой класс для разграничения доступа к базе, либо в во всем коде, где идет работа с базой делать проверки на busy и lock, ожидания пока блокировка уйдет и повторной попытки выполнить операцию. Мне кажется, что свой класс для разруливания доступа будет проще.

Используй FireBird embedded тогда, раз метаданные активно менять не собираешься. А для временных данных - используй GTT.
Все вылизано и просто работает.

Из разных нитей коннектишься к базе, и просто работаешь с базой, и все. А в случае надобности перейти на удаленный сервер - всего лишь изменишь строку коннекта.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489151
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот на stackoverflow https://stackoverflow.com/questions/1680249/how-to-use-sqlite-in-a-multi-threaded-application пишут:

Your sqlite3_step, sqlite3_prepare and some other calls may return SQLITE_BUSY or SQLITE_LOCKED. SQLITE_BUSY usually means that sqlite needs to acquire the lock. The biggest difference between the two return values:

SQLITE_LOCKED: if you get this from a sqlite3_step statement, you MUST call sqlite3_reset on the statement handle. You should only get this on the first call to sqlite3_step, so once reset is called you can actually "retry" your sqlite3_step call. On other operations, it's the same as SQLITE_BUSY
SQLITE_BUSY : There is no need to call sqlite3_reset, just retry your operation after waiting a bit for the lock to be released.

Вот ради того чтобы этого избежать все и делается.

В остальном, я думаю, вопрос можно закрывать. Попробуем это:

авторТот который эксклюзивно пишет, вначале делает AtomicIncrement(FWrite) и event.reset в конце AtomicDecrement(FWrite); event.set Остальные вначале делают проверку на if AtomicCmpExchange(FWrite, 0, 0) > 0 then ждем сигнал event
и далее разруливаем TMultiReadExclusiveWriteSynchrinizer

Если не получится или вылезут подводные камни - видимо придется таки переходить на FireBird.

Все большое спасибо за участие и советы !
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489162
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdev...
Если не получится или вылезут подводные камни - видимо придется таки переходить на FireBird.
...- Скажите, а где тут поезд на Одессу?
- Он уже ушел.
- Вот бл?*:!, а куда?
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489163
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В остальном, я думаю, вопрос можно закрывать. Попробуем это:[/quot]
Только аккуратно, там есть один момент
авторОстальные вначале делают проверку на if AtomicCmpExchange(FWrite, 0, 0) > 0 then ждем сигнал event
Если вдруг отработало сравнение, но еще не дошли до ожидания ивента, а монопольный врайтер опять запустился и процессор переключился и там успел отработать только AtomicIncrement(FWrite) до event.reset.. то будет косяк.
По сути, в остальных потоках до if AtomicCmpExchange(FWrite, 0, 0) > 0 then надо что-то взводить, но так, чтобы монопольный врайтер до AtomicIncrement(FWrite) уже ждал их. Вообщем синхронизация штука сложная, но интересная...
Я бы наверное вот так сделал:
Поток эксклюзивного врайтера:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  TMonitor.Enter(FLockWrite);
  try
    if AtomicCmpExchange(FTotalCall, 0, 0) > 0 then
      FQueryEmpty.WaitFor(INFINITE);
    // Пишем
  finally
    TMonitor.Exit(FLockWrite);
  end;


Поток всех неэксклюзивных врайторидеров:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
  TMonitor.Enter(FLockWrite);
  try
    AtomicIncrement(FTotalCall);
    FQueueEmpty.ResetEvent();
  finally
    TMonitor.Exit(FLockWrite);
  end;
  try
    // Читаем/Пишем разруливаем их TMultiReadExclusiveWriteSynchrinizer или еще чем между собой.
  finally
    AtomicDecrement(FTotalCall);
    if AtomicCmpExchange(FTotalCall, 0, 0) = 0 then
      FQueueEmpty.SetEvent();
  end;


Суть такова, что если монопольщику надо писать, то он ставит блокировку и ждет когда все перестанут что-то делать.
Все новые не начнут работать, т.к. станут в очередь за мнопольщиком, а все старые спокойно доработают и последний который закончит, выставит FTotalCall в 0 и дернет ивент для монопольщика.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489167
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отдельный поток под запись, которому все будут скидывать задания, нельзя сделать?
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489168
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Большое спасибо ! Попробуем !
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489333
MaratIsk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdev,
после слов - сreate table/drop table - остается только ставить диагноз творцу
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489341
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaratIskamsdev,
после слов - сreate table/drop table - остается только ставить диагноз творцуНу и что. Зато сколько драйва.

amsdevСвой планировщик нужен для того, чтобы исключить ошибки busy/locked sqlite и таким образом упростить их обработкуВсе, что угодно, лишь бы не разбираться в существующей системе.

PS: почему-то вспомнился первый аргумент "сторонников ORM": "не нужно знать SQL"...
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489343
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, пишут, что работа с временными ("в памяти" или "отдельный файл") табличками SQLite основной файл базы не блокируется.
Хотя, возможно, ТС и к временным табличкам собрался ходить параллельно, из разных потоков...
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489517
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторпосле слов - сreate table/drop table - остается только ставить диагноз творцу

Вы думаете, что create/drop table будет из-за того, что так хочется моей правой ноге ? Нет, все очень внимательно продумывалась и это нужно в силу ряда обстоятельств. И я скажу больше - некоторые большие "справочники" будут в отдельных базах данных т.е. в отдельных файлах, да ) И работа с ними будет через ATTACH DATABASE. Так надо )

авторВсе, что угодно, лишь бы не разбираться в существующей системе.

Читаем это:

авторYour sqlite3_step, sqlite3_prepare and some other calls may return SQLITE_BUSY or SQLITE_LOCKED. SQLITE_BUSY usually means that sqlite needs to acquire the lock. The biggest difference between the two return values:

SQLITE_LOCKED: if you get this from a sqlite3_step statement, you MUST call sqlite3_reset on the statement handle. You should only get this on the first call to sqlite3_step, so once reset is called you can actually "retry" your sqlite3_step call. On other operations, it's the same as SQLITE_BUSY
SQLITE_BUSY : There is no need to call sqlite3_reset, just retry your operation after waiting a bit for the lock to be released.

Т.е. возможны два вида ошибок у TQuery.Prepare, TQuery.Open, TQuery.Next и DataBase.StartTransaction/Commit. И в одном случае нужно переоткрыть запрос, а в другом пытаться еще несколько раз по таймеру. Если же самому управлять тем как потоки читают/пишут в базу можно полностью, с гарантией 100% исключить проблемы с busy/locked и не контролировать эти ошибки везде в коде где идет работа с базой.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489549
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdev...

авторВсе, что угодно, лишь бы не разбираться в существующей системе.

Читаем это:

авторYour sqlite3_step, sqlite3_prepare and some other calls may return SQLITE_BUSY or SQLITE_LOCKED. SQLITE_BUSY usually means that sqlite needs to acquire the lock. The biggest difference between the two return values:

SQLITE_LOCKED: if you get this from a sqlite3_step statement, you MUST call sqlite3_reset on the statement handle. You should only get this on the first call to sqlite3_step, so once reset is called you can actually "retry" your sqlite3_step call. On other operations, it's the same as SQLITE_BUSY
SQLITE_BUSY : There is no need to call sqlite3_reset, just retry your operation after waiting a bit for the lock to be released.

Т.е. возможны два вида ошибок у TQuery.Prepare, TQuery.Open, TQuery.Next и DataBase.StartTransaction/Commit. И в одном случае нужно переоткрыть запрос, а в другом пытаться еще несколько раз по таймеру. Если же самому управлять тем как потоки читают/пишут в базу можно полностью, с гарантией 100% исключить проблемы с busy/locked и не контролировать эти ошибки везде в коде где идет работа с базой.
Нет никакой "проблемы" с busy/locked, это ШТАТНОЕ поведение, а не ошибки. И это поведение позволяет продолжить вычислительный процесс, а не перевести в тупое состояние ожидания доступности базы. Ты, если и реализуешь свой "диспетчер", в итоге в придешь к тому же самому (в лучшем случае).
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489577
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdevВы думаете, что create/drop table будет из-за того, что так хочется моей правой ноге ? Нет, все очень внимательно продумывалась и это нужно в силу ряда обстоятельств. И я скажу больше - некоторые большие "справочники" будут в отдельных базах данных т.е. в отдельных файлах, да ) И работа с ними будет через ATTACH DATABASE. Так надо )

Жесть... Еще больше уверен, что нужен толковый архитектор.
Либо это саботаж.
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39489581
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdev>>это нужно в силу ряда обстоятельств.
>>Так надо

сразу вспоминается, что примерно так же я отвечал, когда мне указывали на shit-code и предлагали отрефакторить\переписать огромный класс в 300 кб размером, а мне было лень :)
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39493323
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторЖесть... Еще больше уверен, что нужен толковый архитектор.
Либо это саботаж.

Вы понятия не имеете о специфике задачи, а предлагаете архитекторов, этого не надо. Вопрос был про многоуровневую синхронизацию потоков. Вы в курсе как это сделать наилучшим образом ? Нет ? :-)

авторНет никакой "проблемы" с busy/locked, это ШТАТНОЕ поведение, а не ошибки. И это поведение позволяет продолжить вычислительный процесс, а не перевести в тупое состояние ожидания доступности базы. Ты, если и реализуешь свой "диспетчер", в итоге в придешь к тому же самому (в лучшем случае).

Может и нет если работать с sqlite api напрямую. Но мы работаем через LiteDac/TDataSet, а для TDataSet это "штатное" поведение не является штатным.

Вообще вопрос был про многоуровневую синхронизацию потоков. Sqlite или нет - не имеет значения. Кто-то кроме X-Cite знает как это сделать ? Советчики архитекторов и учителя работать с sqlite не нужны :-)
...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39493369
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
amsdevВопрос был про многоуровневую синхронизацию потоков.отлично, сколько уровней должно быть?

Если три, то одной внешней (для всех) и ещё одной вложенной (для приоритетных и сверхприоритетных) SRWLock должно хватить.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Low:

AcquireSRWLockShared(Lo);
 Work();
ReleaseSRWLockShared(Lo);


Norm:

AcquireSRWLockExclusive(Lo);
 AcquireSRWLockShared(Li);
  Work();
 ReleaseSRWLockShared(Li);
ReleaseSRWLockExclusive(Lo);


High:

AcquireSRWLockExclusive(Lo);
 AcquireSRWLockExclusive(Li);
  Work();
 ReleaseSRWLockExclusive(Li);
ReleaseSRWLockExclusive(Lo);

...
Рейтинг: 0 / 0
Многоуровневая блокировка/синхронизация потоков
    #39496781
amsdev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо ! Попробуем !
...
Рейтинг: 0 / 0
19 сообщений из 44, страница 2 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Многоуровневая блокировка/синхронизация потоков
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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