|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Приветствую! Использую связку myBatis и PostgreSQL. Приложение делает инсерт в таблицу [table1], вызывает метод push() и параллельный поток делает селект из этой же таблицы [table1] и обрабатывает полученные записи для дальнейшего анализирования. myBatis использует пул потоков к PostgreSQL. В какой-то момент, получается так, что инсерт и селект происходят почти в одно и то же время (разница 0.002 мс) и селект не видит новых записей. Код инсерта: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Код селекта: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Подскажите, может кто сталкивался, как это разруливается. Пробовал ставить в SqlMapHelper.getSqlSessionFactory().openSession isolation level READ COMMITED, но все равно не видит. Спасибо! ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 06:16 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip, Так все правильно! Разные транзакции. Транзакция для insert еще не закончилась, а транзакция для select уже началась. Можно попробовать "грязное чтение", тогда возможно, будет работать как вам надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 06:47 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip как это разруливается. Код исправно ПАРАЛЛЕЛЬНО И НЕЗАВИСИМО работает. Когда то первым будет чтение, когда то вставка. Вам это не нравится. В чем проблема? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 07:17 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
mad_nazgul qi_ip, Так все правильно! Разные транзакции. Транзакция для insert еще не закончилась, а транзакция для select уже началась. Можно попробовать "грязное чтение", тогда возможно, будет работать как вам надо. Метод push() по коду вызывается уже после того, как произошел sqlSession.commit(); , поэтому теоретически select из другого потока должен (не факт) видеть сохраненную запись? Или я не прав? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 08:32 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
PetroNotC Sharp qi_ip как это разруливается. Код исправно ПАРАЛЛЕЛЬНО И НЕЗАВИСИМО работает. Когда то первым будет чтение, когда то вставка. Вам это не нравится. В чем проблема? Ну проблема как раз выше описал, что сначала происходит sqlSession.commit(); , потом инициируется метод, где открывается новая транзакция для чтения этой записи, но ее не читает ))) хотя теоретически если commit не fail, то запись уже в БД. Но это только теория... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 08:37 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip поэтому теоретически select из другого потока должен (не факт) видеть сохраненную запись? Или я не прав? Поставь логирование и дай сюда лог. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 08:54 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip mad_nazgul qi_ip, Так все правильно! Разные транзакции. Транзакция для insert еще не закончилась, а транзакция для select уже началась. Можно попробовать "грязное чтение", тогда возможно, будет работать как вам надо. Метод push() по коду вызывается уже после того, как произошел sqlSession.commit(); , поэтому теоретически select из другого потока должен (не факт) видеть сохраненную запись? Или я не прав? Не совсем. Т.к. взаимодествие асинхронное, то нужно еще время для PostgreSQL, чтобы "закрыть" транзакцию. Так что что будет и как - фиг его знает. Зависит еще от скорости PostgreSQL. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 11:04 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip, попробуйте использовать одну сессию (если это возможно) и для инсерта и для селекта, т е вот этот код: Код: java 1.
выполняйте только один раз ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 11:46 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov, В разных потоках нельзя. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:01 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
PetroNotC Sharp В разных потоках нельзя. - почему это? синхронизацию потоков ручками сделать и передавать инстанс SqlSession с комитом при выходе из синхронизированного куска кода ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:28 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
А так? Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:35 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov, Да он вообще ошибся со своей ошибкой. Должен быть видно все что закоммичено в другом соединении. А в этом и подавно. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:39 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov почему это? 1. Не потокобезопасен ни класс ни драйвер. 2. Можно синронизировать и тормозить БЛ. Зачем тогда параллелили? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:40 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
PetroNotC Sharp Kachalov, Да он вообще ошибся со своей ошибкой. Должен быть видно все что закоммичено в другом соединении. А в этом и подавно. Вообще зависит от реализации. Хз что commit() делает. Гарантированно данные будут записаны, когда закончится нативная транзакция у Postgres, а вот то что она закнчивается на commit() никто не гарантирует. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:41 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
PetroNotC Sharp 1. Не потокобезопасен ни класс ни драйвер. - еще раз: синхронизацию сделать самостоятельно PetroNotC Sharp 2. Можно синронизировать и тормозить БЛ. Зачем тогда параллелили? - а зачем селект после инсерта? такая бизнес логика ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:43 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
забыл ник Хз что commit() делает. Гарантированно данные будут записаны, когда закончится нативная транзакция у Postgres, а вот то что она закнчивается на commit() никто не гарантирует. - понятно что там еще кэши есть и у MyBatis, и дальше. Но на уровне кэша MyBatis в одной сессии данные врядли противоречивы ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:46 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov забыл ник Хз что commit() делает. Гарантированно данные будут записаны, когда закончится нативная транзакция у Postgres, а вот то что она закнчивается на commit() никто не гарантирует. - понятно что там еще кэши есть и у MyBatis, и дальше. Но на уровне кэша MyBatis в одной сессии данные врядли противоречивы Наверное можно, но мне кажется проще правильно написать push - чтобы он уже отрабатывал когда сессия закрылась, тогда не важно будет из какой сессии идет селект ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:52 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
qi_ip, современные базы данных оперируют не insert-ами а транзакциями. Транзакция это более общее понятие. Обычно оно охватывает пакет изменений. Это сделано для того чтобы в сложной системе не было аномалий типа ты переводил деньги с 1 счета на другой и деньги вдруг внезапно исчезли навсегда. Тоесть чтение должно быть консистентным по отношению к бизнес-операциям. То о чем ты пишешь это dirty-read. Это бывает когда работаешь с двоичными файлами. Если ты хочешь организовать коммуникацию двух java-потоков эффективно (producer-consumer) то надо делать чтобы продюсер уведомлял консюмера через очереди или JMS о том что он закончил порцию операций и она закоммичена и с ней можно работать. Но и даже в таком виде КПД твоей двухпоточной системы будет невысоким т.к. консюмер будет все равно вычитывать объем инфы чуть больше чем ему надо на самом деле. Как бороться с этим - я пока не знаю это глубоко архитектурный вопрос и надо понимать что ты делаешь на самом деле. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 12:58 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
mayton надо делать чтобы продюсер уведомлял консюмера через очереди или JMS о том что он закончил порцию операций и она закоммичена и с ней можно работать. - я так понял, что у ТС парадокс в том, что он примерно так все и сделал: закомитил (на уровне MyBatis), и оповестил что можно читать и тут облом - данных в базе еще нет ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:25 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
забыл ник PetroNotC Sharp Kachalov, Да он вообще ошибся со своей ошибкой. Должен быть видно все что закоммичено в другом соединении. А в этом и подавно. Вообще зависит от реализации. Хз что commit() делает. Гарантированно данные будут записаны, когда закончится нативная транзакция у Postgres, а вот то что она закнчивается на commit() никто не гарантирует. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:31 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov а зачем селект после инсерта? такая бизнес логика То что нужно делать после не делают в другом потоке. Пусть логи даст. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:33 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
забыл ник Kachalov пропущено... - понятно что там еще кэши есть и у MyBatis, и дальше. Но на уровне кэша MyBatis в одной сессии данные врядли противоречивы Наверное можно, но мне кажется проще правильно написать push - чтобы он уже отрабатывал когда сессия закрылась, тогда не важно будет из какой сессии идет селект - можно теоретически усложнить задачу (чисто гипотетически, чтобы обсудить интересную архитектурную проблему) и предположить что речь идет о двух различных сервисах (допустим у нас SOA). Везде есть свои кэши, буфера, сетевые соединения, но БД общая (транзакции разные, коннекты к ней разные и т д, т е все легитимно). Один сервис пишет в БД, другой читает когда получает извещение через шину сообщений. Проблема: сообщение о записи через шину приходит раньше, чем данные фактически попадают в БД и становятся доступны для чтения. Пока вижу принципиально два решения (и оба не очень): 1) читать данные из общего кэша, т е до того как они фактически попали в БД и стали доступны для чтения; 2) проверять доступность данных в БД (тут варианты как, но все кривые) и уже тогда посылать извещение. Еще идеи? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:38 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov, В SOA только второй вариант. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:41 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Kachalov, Если он читает, а данных нет, значит их нет (с) И никакой проблемы. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 13:42 |
|
Mybatis+PostgreSQL паралелльные потоки
|
|||
---|---|---|---|
#18+
Если он их закоммитил и следующая читающая транзакция их не видит значит либо режим изоляции читающей транзакции таков. Либо нарушена какая-то причинно-следственная связь и читающий находится в далёком будущем. Я думаю что старик Эйнштейн с этим не согласится. И я тоже. Поэтому надо логи. С точностью таймингов до милисекунд и будем разбираться. Я не работал с SqlMapHelper и не вижу под капотом какие там режими изоляции. Поэтому надо также чтоб кто-то знающий подтвердил что "оно так". Или "не так". ... |
|||
:
Нравится:
Не нравится:
|
|||
21.11.2019, 14:08 |
|
|
start [/forum/topic.php?fid=59&msg=39892251&tid=2120990]: |
0ms |
get settings: |
7ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
74ms |
get topic data: |
3ms |
get forum data: |
1ms |
get page messages: |
432ms |
get tp. blocked users: |
1ms |
others: | 6ms |
total: | 531ms |
0 / 0 |