Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5beea95

Browse files
committed
pg_dump: Lock all relations, not just plain tables
Now that LOCK TABLE can take any relation type, acquire lock on allrelations that are to be dumped. This prevents schema changes ordeadlock errors that could cause a dump to fail after expending mucheffort. The server is tested to have the capability and the featuredisabled if it doesn't, so that a patched pg_dump doesn't fail whenconnecting to an unpatched server.Backpatch to 9.5.Author: Álvaro Herrera <alvherre@alvh.no-ip.org>Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>Reported-by: Wells Oliver <wells.oliver@gmail.com>Discussion:https://postgr.es/m/20201021200659.GA32358@alvherre.pgsql
1 parent2f0baa2 commit5beea95

File tree

4 files changed

+79
-7
lines changed

4 files changed

+79
-7
lines changed

‎src/bin/pg_dump/pg_backup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ typedef struct Archive
197197
intminRemoteVersion;/* allowable range */
198198
intmaxRemoteVersion;
199199

200+
boolhasGenericLockTable;/* can LOCK TABLE do non-table rels */
201+
200202
intnumWorkers;/* number of parallel processes */
201203
char*sync_snapshot_id;/* sync snapshot id for parallel operation */
202204

‎src/bin/pg_dump/pg_backup_db.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,71 @@ EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
537537
}
538538
}
539539

540+
/*
541+
* Does LOCK TABLE work on non-table relations on this server?
542+
*
543+
* Note: assumes it is called out of any transaction
544+
*/
545+
bool
546+
IsLockTableGeneric(Archive*AHX)
547+
{
548+
ArchiveHandle*AH= (ArchiveHandle*)AHX;
549+
PGresult*res;
550+
char*sqlstate;
551+
boolretval;
552+
553+
if (AHX->remoteVersion >=140000)
554+
return true;
555+
elseif (AHX->remoteVersion<90500)
556+
return false;
557+
558+
StartTransaction(AHX);
559+
560+
/*
561+
* Try a LOCK TABLE on a well-known non-table catalog; WRONG_OBJECT_TYPE
562+
* tells us that this server doesn't support locking non-table rels, while
563+
* LOCK_NOT_AVAILABLE and INSUFFICIENT_PRIVILEGE tell us that it does.
564+
* Report anything else as a fatal problem.
565+
*/
566+
#defineERRCODE_INSUFFICIENT_PRIVILEGE"42501"
567+
#defineERRCODE_WRONG_OBJECT_TYPE"42809"
568+
#defineERRCODE_LOCK_NOT_AVAILABLE"55P03"
569+
res=PQexec(AH->connection,
570+
"LOCK TABLE pg_catalog.pg_class_tblspc_relfilenode_index IN ACCESS SHARE MODE NOWAIT");
571+
switch (PQresultStatus(res))
572+
{
573+
casePGRES_COMMAND_OK:
574+
retval= true;
575+
break;
576+
casePGRES_FATAL_ERROR:
577+
sqlstate=PQresultErrorField(res,PG_DIAG_SQLSTATE);
578+
if (strcmp(sqlstate,ERRCODE_WRONG_OBJECT_TYPE)==0)
579+
{
580+
retval= false;
581+
break;
582+
}
583+
elseif (strcmp(sqlstate,ERRCODE_LOCK_NOT_AVAILABLE)==0||
584+
strcmp(sqlstate,ERRCODE_INSUFFICIENT_PRIVILEGE)==0)
585+
{
586+
retval= true;
587+
break;
588+
}
589+
/* else, falls through */
590+
default:
591+
warn_or_exit_horribly(AH,modulename,
592+
"LOCK TABLE failed for \"%s\": %s",
593+
"pg_catalog.pg_class_tblspc_relfilenode_index",
594+
PQerrorMessage(AH->connection));
595+
retval= false;/* not reached */
596+
break;
597+
}
598+
PQclear(res);
599+
600+
CommitTransaction(AHX);
601+
602+
returnretval;
603+
}
604+
540605
void
541606
StartTransaction(Archive*AHX)
542607
{

‎src/bin/pg_dump/pg_backup_db.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ extern PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
2020

2121
externvoidEndDBCopyMode(Archive*AHX,constchar*tocEntryTag);
2222

23+
externboolIsLockTableGeneric(Archive*AHX);
24+
2325
externvoidStartTransaction(Archive*AHX);
2426
externvoidCommitTransaction(Archive*AHX);
2527

‎src/bin/pg_dump/pg_dump.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,9 @@ setup_connection(Archive *AH, const char *dumpencoding,
10991099
ExecuteSqlStatement(AH, "SET row_security = off");
11001100
}
11011101

1102+
/* Detect whether LOCK TABLE can handle non-table relations */
1103+
AH->hasGenericLockTable = IsLockTableGeneric(AH);
1104+
11021105
/*
11031106
* Start transaction-snapshot mode transaction to dump consistent data.
11041107
*/
@@ -6338,16 +6341,16 @@ getTables(Archive *fout, int *numTables)
63386341
* assume our lock on the child is enough to prevent schema
63396342
* alterations to parent tables.
63406343
*
6341-
* NOTE: it'd be kinda nice to lock other relations too, not only
6342-
* plain or partitioned tables, but the backend doesn't presently
6343-
* allow that.
6344-
*
6345-
* We only need to lock the table for certain components; see
6344+
* We only need to lock the relation for certain components; see
63466345
* pg_dump.h
6346+
*
6347+
* On server versions that support it, we lock all relations not just
6348+
* plain tables.
63476349
*/
63486350
if (tblinfo[i].dobj.dump &&
6349-
(tblinfo[i].relkind == RELKIND_RELATION ||
6350-
tblinfo->relkind == RELKIND_PARTITIONED_TABLE) &&
6351+
(fout->hasGenericLockTable ||
6352+
tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE ||
6353+
tblinfo[i].relkind == RELKIND_RELATION) &&
63516354
(tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
63526355
{
63536356
resetPQExpBuffer(query);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp