powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Запись из разных потоков в одну таблицу
28 сообщений из 28, показаны все 2 страниц
Запись из разных потоков в одну таблицу
    #38799458
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.
Нужна помощь, как правильно алгоритмически решить следующую задачу:
Есть несколько файлов размером до 500 Мб, необходимо распарсить каждый файл в отдельном потоке и записать их все в одну таблицу, при этом если возникли проблемы при парсинге или записи в таблицу, то нужно удалить все вставленные данные до появления ошибки. После того как содержимое конкретного файла было обработано и вставлено в таблицу необходимо для вставленных данных для каждого файла заполнить колонку вычислив значение и если обновление прошло успешно то пометить что файлы были записаны корректно и удалить файл

Я попробовал решить это следующим образом БД MSSQL и java

- Создаю поток и в нем делаю следующее
- Открываю коннект к БД и ставлю autocommit=false
- читаю файл по строчкам и делаю по строчкам insert в таблицу
- После того как пробежался по всем строчкам вызываю UPDATE в котором заполняю колонку (с помощью ROW_NUMBER() OVER (PARTITION BY ___ order by__ )
- Далее вызываю Commit и поток завершает свою работу

Это все прекрасно работает если файл один, но если я открываю три файла и каждый в отдельном потоке, то после завершения первого потока почему-то два других потока выдают ошибку
Exception:java.sql.SQLException: Invalid state, the Connection object is closed.

Как такое может происходить?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799464
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Извиняюсь, не ту ошибку скопировал
Exception:java.sql.SQLException: Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Вопрос, как мне избавится от деадлоков? Может Isolation LEVEL изменить или еще что-то?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799485
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
надо использовать разные Connection для каждого потока, ну и соотвественно коннекшен пул
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799487
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ааа ну так это все меняет. Попробуй не писать каждый инсерт сразу а собрать их все вместе, и потом записывай. Гугли BatchInsert, таким образом риск дедлоков уменьшится. Хотя сама ошибка никуда не уйдет, тут надо смотреть что именно лочится, и почему дедлок средствами бд
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799489
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799538
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл ник,
С конфетками вроде разобрался)

Остались deadlock!
Я понимаю что лочится из-за апдейта, который я выполняю, но как тут быть непонятно. Суть проблемы в том, что одновременно инсертятся данные из трех потоков в одну таблицу, а потом мне нужно сделать update, который апдейтит данные вставленные в таблицу внутри каждого потока. Update выглядит следующим образом:
Код: sql
1.
2.
3.
4.
5.
UPDATE x SET x.column1 = x.New_CODE, x.column2 = x.New_CODE1 FROM ( SELECT  column1,column2
                                        ROW_NUMBER() OVER (PARTITION BY row1 order by column1) AS New_CODE, 
                                        ROW_NUMBER() OVER (PARTITION BY row2 order by column2) AS NEW_CODE1 
                                        FROM result where attempt IS NOT NULL AND attempt> 0
                                        AND primarykey BETWEEN firstLineID AND lastLineID AND listid = "123") x );



Вроде от deadlock получилось избавиться с помощью Isolation level SNAPSHOT. На небольших файлах работает хорошо. Но при вставке 3х файлов по 400 мб выскакивает ошибка:

Exception:java.sql.SQLException: The instance of the SQL Server Database Engine cannot obtain a LOCK resource at this time. Rerun your statement when there are fewer active users. Ask the database administrator to check the lock and memory configuration for this instance, or to check for long-running transactions.

То ли я очень сильно нагружаю БД, то ли изначально подход неправильный к решению
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799547
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jeddite,
кто мешает отделить мух от котлет?
Потоками разбери файлы в один массив (если хватит оперативки). А потом батчем за раз вставь в БД его форматом и максимально быстро.
Либо разбирайся с локами. На блокировочнике ты всегда можешь схватить в неожиданном месте.
....
Зачем бить на потоки задачу, если все файлы в одном откате и транзакции?
авторесли обновление прошло успешно то пометить что файлы были записаны
файлы или файл?
ЗЫ. Про коннект в потоке верно сказали.
...
Ещё можно готовить файлы во временной табле, а потом одним запросом перебросить в основную.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799549
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jedditeUpdate выглядит следующим образом
на ветке по БД закинь вопрос по запросу
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799573
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jeddite,

Приведите нормальный запрос, который хотя бы будет синтаксически верным.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799576
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petro123,

Оперативки то и не хватит т.к. файлы по 500 мб и сейчас их три а может быть и больше. batch можно частями выполнять и наверно перепишу код. и как я уже писал файлы должны обрабатываться отдельно и возможно в разное время


Вот можно ли insert с апдейтом объединить ?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799582
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123На блокировочнике ты всегда можешь схватить в неожиданном месте.
Ну как бы
jeddite Isolation level SNAPSHOT
не совсем про блокировочник. А к операциям по конкурентному изменению данных и возникающих при этом deadlock'ах это имеет еще меньшее отношение.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799588
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Локшин Марк,

Вот этот запрос используется, взял из лога

Код: sql
1.
UPDATE x SET x.Attempt1 = x.New_CODE, x.Attempt2 = x.New_CODE1 FROM (SELECT Attempt1,Attempt2, ROW_NUMBER() OVER (PARTITION BY chain_id order by call_time) AS New_CODE, ROW_NUMBER() OVER (PARTITION BY order_number order by call_time) AS NEW_CODE1 FROM [DLDDB].[dbo].[result] where  ID BETWEEN 9320889 AND 9320944 AND list_id = 123) x
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799620
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Локшин МаркPetro123На блокировочнике ты всегда можешь схватить в неожиданном месте.
Ну как бы
jeddite Isolation level SNAPSHOT
не совсем про блокировочник. А к операциям по конкурентному изменению данных и возникающих при этом deadlock'ах это имеет еще меньшее отношение.

Ну почему же не про блокировки? При таком подходе каждый поток работает со своим snapshot и блокировок не происходит
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799653
YamahaR1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jeddite,

Сколько вы записей апдейтите? Посмотрите тут еще http://www.sqlusa.com/bestpractices/largeupdate/
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799667
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YamahaR1,

Где-то 1 900 000 записей
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799739
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jedditeИзвиняюсь, не ту ошибку скопировал
Exception:java.sql.SQLException: Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Вопрос, как мне избавится от деадлоков? Может Isolation LEVEL изменить или еще что-то?
убери UPDATE из этой транзакций.
либо сразу при insert генерируй значение этого поля либо делай это в отдельной транзакции .
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799776
jeddite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,
У меня задача отслеживать целостность данных и если апдейт в отдельную транзакцию вынести, то как контролировать целостность..мне нужно быть уверенным на 100 процентов, что данные закомитятся только в том случае если апдейт был выполнен...не используя одну большую транзакцию это можно как-то сделать?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38799857
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Если при разборе могут быть ошибки, то сначала должен делаться разбор файла и только после этого должна начинаться вставка подготовленных значений.
2. Никаких "сначала вставка, потом обновление" быть не должно. Если в процессе вставки обнаружена проблема, то rollback откатывает всю транзакцию, если проблем не было, то commit фиксирует всю транзакцию. Со всеми актуальными значениями.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38800090
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jedditeНу почему же не про блокировки? При таком подходе каждый поток работает со своим snapshot и блокировок не происходит
Вот именно, что пассаж про блокировочник здесь не к месту.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38800144
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Локшин МаркjedditeНу почему же не про блокировки? При таком подходе каждый поток работает со своим snapshot и блокировок не происходит
Вот именно, что пассаж про блокировочник здесь не к месту.
угу.
Верю, что на миллионах записей, сиквел одной галкой превращается в оракл (неБлокировочник).
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38800283
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jedditeИзвиняюсь, не ту ошибку скопировал
Exception:java.sql.SQLException: Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Вопрос, как мне избавится от деадлоков? Может Isolation LEVEL изменить или еще что-то?
На SQL Server так лучше не делать совсем. Множество долгоживущих транзакций вставляющих в одну таблицу. Вы никогда таким образом дедлоки не разрулите.

Я бы завел временную таблицу для каждого Thread/Connection и писал бы все данные в эту таблицу. Временная таблица у каждого Connection своя. При ошибке, временную таблицу можно удалить. Да, она и сама умрет при закрытии соединения. А вот при завершении обработки нужно вызвать одну быструю операцию копирования из временной таблицы в основную. Тогда потоки никак не будут мешать друг другу. И не будет длинных транзакций.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801339
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Локшин Маркпропущено...

Вот именно, что пассаж про блокировочник здесь не к месту.
угу.
Верю, что на миллионах записей, сиквел одной галкой превращается в оракл (неБлокировочник).
И как же ваш неБлокировочнир разруливает конкурентные UPDATE'ы? Наверное версиями?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801414
YamahaR1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczjedditeИзвиняюсь, не ту ошибку скопировал
Exception:java.sql.SQLException: Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Вопрос, как мне избавится от деадлоков? Может Isolation LEVEL изменить или еще что-то?
На SQL Server так лучше не делать совсем. Множество долгоживущих транзакций вставляющих в одну таблицу. Вы никогда таким образом дедлоки не разрулите.

Я бы завел временную таблицу для каждого Thread/Connection и писал бы все данные в эту таблицу. Временная таблица у каждого Connection своя. При ошибке, временную таблицу можно удалить. Да, она и сама умрет при закрытии соединения. А вот при завершении обработки нужно вызвать одну быструю операцию копирования из временной таблицы в основную. Тогда потоки никак не будут мешать друг другу. И не будет длинных транзакций.

Ну а если например будет производиться одновременное копирование данных из трех потоков в одну таблицу, это не приведет к дедлоку?
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801515
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Локшин Марк,
Устройство БД, JS и т.д. в соседней ветке.
Java эффективно делает crud а не ETL
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801520
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YamahaR1,
3 потока это 3 коннекта.
При плохом Update сервер ходит по всем записям.
При вставке это не нужно.
Все это можно посмотреть и спросить у БД.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801535
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YamahaR1Ну а если например будет производиться одновременное копирование данных из трех потоков в одну таблицу, это не приведет к дедлоку?
Не должно. Там же только вставка будет. Причем заточеная под множество записей, в отличие от последовательной вставке\обновлении в процессе обработки данных.
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801855
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jedditeНу почему же не про блокировки? При таком подходе каждый поток работает со своим snapshot и блокировок не происходит
А что происходит, когда снапшот надо поправить, а он устарел?

Проблема взаимных блокировок в том, что Вы толком не говорите СУБД, что хотите работать с данными только своей сессии.
Другими словами New_CODE и NEW_CODE1 присваиваются только в рамках 1 сессии или могут перенумеровывать данные другой сессии (произошедшей ранее и не только).
...
Рейтинг: 0 / 0
Запись из разных потоков в одну таблицу
    #38801883
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Грубо говоря алгоритм параллельной вставки с обработкой вставленного выглядит следующим образом.

1. Создается транзакция
2. Создается временная таблица с данными только этой транзакции.
3. Временная таблица заполняется insert (с проверкой самосогласованности строки).
4. Временная таблица обрабатывается (update с перенумеровкой).
5. Содержимое временной таблицы вставляется целиком в основную.
6. транзакция завершается.

Если же перенумерация связана с данными в основной таблице, то
3а. Захватываем некоторую глобальную блокировку.

Если же надо менять и другие записи из основной таблицы (3а как есть)

4. Содержимое временной таблицы вставляется целиком в основную.
5. Основная таблица обрабатывается.
...
Рейтинг: 0 / 0
28 сообщений из 28, показаны все 2 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / Запись из разных потоков в одну таблицу
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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