Re: deadlock between "WITH agg_tmp AS ({sel_stmt}), upd AS ({upd_stmt}) {ins_stmt}" and pure UPDATE statements
От | Adrian Klaver |
---|---|
Тема | Re: deadlock between "WITH agg_tmp AS ({sel_stmt}), upd AS ({upd_stmt}) {ins_stmt}" and pure UPDATE statements |
Дата | |
Msg-id | 50d4f011-0eea-0c97-fbc8-5873cd9caebb@aklaver.com обсуждение исходный текст |
Ответ на | deadlock between "WITH agg_tmp AS ({sel_stmt}), upd AS ({upd_stmt}) {ins_stmt}" and pure UPDATE statements (trafdev <trafdev@mail.ru>) |
Ответы |
Re: deadlock between "WITH agg_tmp AS ({sel_stmt}), upd AS
({upd_stmt}) {ins_stmt}" and pure UPDATE statements
|
Список | pgsql-general |
On 07/02/2016 09:54 AM, trafdev wrote: > Hello. > > I have two transactions (trans1 and trans2) updating tables T1 and T2 in > the same order, but in a different way. > > trans1 creates temp table, copies data from a file and updates tables T1 > and T2 from this temp table (using basic UPDATE form). It even commits > changes in between T1 and T2 updates to reduce locks. > > trans2 creates two temp tables (T1_tmp and T2_tmp), copies data from > files and updates T1 and T2 using [WITH ... AS ... RETURNING] approach. > Unexciting rows should be inserted, existing updated (sum-ed with values > from temp tables). Both T1 and T2 must be updated in the same transaction. > > There are no any FKs anywhere in these tables. > > > > trans1: > > DROP TABLE IF EXISTS trans1_T_tmp; > > CREATE TABLE trans1_T_tmp (...); > > COMMIT > > COPY from FILE into trans1_T_tmp; > > BEGIN > UPDATE T1 > SET ... > FROM trans1_T_tmp > WHERE ... > COMMIT > > BEGIN > UPDATE T2 > SET ... > FROM (SELECT ... FROM trans1_T_tmp) > WHERE ... > > DROP TABLE trans1_T_tmp; > COMMIT > > > > trans2: > > BEGIN > > CREATE TABLE trans2_T1_tmp (...); > COPY from FILE into trans2_T1_tmp; > WITH agg_tmp AS (SELECT ... FROM trans2_T1_tmp GROUP BY ...), upd AS > (UPDATE T1 SET ... FROM agg_tmp s WHERE ... RETURNING ...) INSERT INTO > T1 (...) SELECT ... FROM agg_tmp s LEFT JOIN upd t ON (...) WHERE ...; > DROP TABLE trans2_T1_tmp; > > CREATE TABLE trans2_T2_tmp (...); > COPY from FILE into trans2_T2_tmp; > WITH agg_tmp AS (SELECT ... FROM trans2_T2_tmp GROUP BY ...), upd AS > (UPDATE T2 SET ... FROM agg_tmp s WHERE ... RETURNING ...) INSERT INTO > T2 (...) SELECT ... FROM agg_tmp s LEFT JOIN upd t ON (...) WHERE ...; > DROP TABLE trans2_T2_tmp; > > COMMIT > > By an unknown [for me] reason trans1 and trans2 often produce deadlocks... > > Could you explain what's the reason for that and how to avoid them? > And is there exist a better replacement for WITH ... AS ... RETURNING ? You did not mention what version of Postgres you are using, if it is 9.5+ you have the 'UPSERT' option available instead of using the WITH construct: https://www.postgresql.org/docs/9.5/static/sql-insert.html ON CONFLICT Clause https://www.depesz.com/2015/05/10/waiting-for-9-5-add-support-for-insert-on-conflict-do-nothingupdate/ If not you might to take a look at: http://stackoverflow.com/questions/17267417/how-to-upsert-merge-insert-on-duplicate-update-in-postgres Bulk upsert with lock > Thanks! > > -- Adrian Klaver adrian.klaver@aklaver.com
В списке pgsql-general по дате отправления: