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

Appearance settings

Commit a575a1a

Browse filesBrowse files
committed
pg_dump: Lock all relations, not just plain tables
Now that LOCK TABLE can take any relation type, acquire lock on all relations that are to be dumped. This prevents schema changes or deadlock errors that could cause a dump to fail after expending much effort. The server is tested to have the capability and the feature disabled if it doesn't, so that a patched pg_dump doesn't fail when connecting 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 parent 53de141 commit a575a1a
Copy full SHA for a575a1a

File tree

Expand file treeCollapse file tree

4 files changed

+79
-5
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+79
-5
lines changed

‎src/bin/pg_dump/pg_backup.h

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_backup.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ typedef struct Archive
188188
int minRemoteVersion; /* allowable range */
189189
int maxRemoteVersion;
190190

191+
bool hasGenericLockTable; /* can LOCK TABLE do non-table rels */
192+
191193
int numWorkers; /* number of parallel processes */
192194
char *sync_snapshot_id; /* sync snapshot id for parallel
193195
* operation */

‎src/bin/pg_dump/pg_backup_db.c

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_backup_db.c
+65Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,71 @@ EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
552552
}
553553
}
554554

555+
/*
556+
* Does LOCK TABLE work on non-table relations on this server?
557+
*
558+
* Note: assumes it is called out of any transaction
559+
*/
560+
bool
561+
IsLockTableGeneric(Archive *AHX)
562+
{
563+
ArchiveHandle *AH = (ArchiveHandle *) AHX;
564+
PGresult *res;
565+
char *sqlstate;
566+
bool retval;
567+
568+
if (AHX->remoteVersion >= 140000)
569+
return true;
570+
else if (AHX->remoteVersion < 90500)
571+
return false;
572+
573+
StartTransaction(AHX);
574+
575+
/*
576+
* Try a LOCK TABLE on a well-known non-table catalog; WRONG_OBJECT_TYPE
577+
* tells us that this server doesn't support locking non-table rels, while
578+
* LOCK_NOT_AVAILABLE and INSUFFICIENT_PRIVILEGE tell us that it does.
579+
* Report anything else as a fatal problem.
580+
*/
581+
#define ERRCODE_INSUFFICIENT_PRIVILEGE "42501"
582+
#define ERRCODE_WRONG_OBJECT_TYPE "42809"
583+
#define ERRCODE_LOCK_NOT_AVAILABLE "55P03"
584+
res = PQexec(AH->connection,
585+
"LOCK TABLE pg_catalog.pg_class_tblspc_relfilenode_index IN ACCESS SHARE MODE NOWAIT");
586+
switch (PQresultStatus(res))
587+
{
588+
case PGRES_COMMAND_OK:
589+
retval = true;
590+
break;
591+
case PGRES_FATAL_ERROR:
592+
sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
593+
if (strcmp(sqlstate, ERRCODE_WRONG_OBJECT_TYPE) == 0)
594+
{
595+
retval = false;
596+
break;
597+
}
598+
else if (strcmp(sqlstate, ERRCODE_LOCK_NOT_AVAILABLE) == 0 ||
599+
strcmp(sqlstate, ERRCODE_INSUFFICIENT_PRIVILEGE) == 0)
600+
{
601+
retval = true;
602+
break;
603+
}
604+
/* else, falls through */
605+
default:
606+
warn_or_exit_horribly(AH, modulename,
607+
"LOCK TABLE failed for \"%s\": %s",
608+
"pg_catalog.pg_class_tblspc_relfilenode_index",
609+
PQerrorMessage(AH->connection));
610+
retval = false; /* not reached */
611+
break;
612+
}
613+
PQclear(res);
614+
615+
CommitTransaction(AHX);
616+
617+
return retval;
618+
}
619+
555620
void
556621
StartTransaction(Archive *AHX)
557622
{

‎src/bin/pg_dump/pg_backup_db.h

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_backup_db.h
+2Lines 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
extern void EndDBCopyMode(Archive *AHX, const char *tocEntryTag);
2222

23+
extern bool IsLockTableGeneric(Archive *AHX);
24+
2325
extern void StartTransaction(Archive *AHX);
2426
extern void CommitTransaction(Archive *AHX);
2527

‎src/bin/pg_dump/pg_dump.c

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_dump.c
+10-5Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,9 @@ setup_connection(Archive *AH, const char *dumpencoding,
10811081
ExecuteSqlStatement(AH, "SET row_security = off");
10821082
}
10831083

1084+
/* Detect whether LOCK TABLE can handle non-table relations */
1085+
AH->hasGenericLockTable = IsLockTableGeneric(AH);
1086+
10841087
/*
10851088
* Start transaction-snapshot mode transaction to dump consistent data.
10861089
*/
@@ -6197,13 +6200,15 @@ getTables(Archive *fout, int *numTables)
61976200
* assume our lock on the child is enough to prevent schema
61986201
* alterations to parent tables.
61996202
*
6200-
* NOTE: it'd be kinda nice to lock other relations too, not only
6201-
* plain tables, but the backend doesn't presently allow that.
6202-
*
6203-
* We only need to lock the table for certain components; see
6203+
* We only need to lock the relation for certain components; see
62046204
* pg_dump.h
6205+
*
6206+
* On server versions that support it, we lock all relations not just
6207+
* plain tables.
62056208
*/
6206-
if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION &&
6209+
if (tblinfo[i].dobj.dump &&
6210+
(fout->hasGenericLockTable ||
6211+
tblinfo[i].relkind == RELKIND_RELATION) &&
62076212
(tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
62086213
{
62096214
resetPQExpBuffer(query);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.