github.com/tuhaihe/gpbackup@v1.0.3/backup/queries_incremental.go (about) 1 package backup 2 3 import ( 4 "fmt" 5 6 "github.com/tuhaihe/gp-common-go-libs/dbconn" 7 "github.com/tuhaihe/gp-common-go-libs/gplog" 8 "github.com/tuhaihe/gpbackup/toc" 9 ) 10 11 func GetAOIncrementalMetadata(connectionPool *dbconn.DBConn) map[string]toc.AOEntry { 12 gplog.Verbose("Querying table row mod counts") 13 var modCounts = getAllModCounts(connectionPool) 14 gplog.Verbose("Querying last DDL modification timestamp for tables") 15 var lastDDLTimestamps = getLastDDLTimestamps(connectionPool) 16 aoTableEntries := make(map[string]toc.AOEntry) 17 for aoTableFQN := range modCounts { 18 aoTableEntries[aoTableFQN] = toc.AOEntry{ 19 Modcount: modCounts[aoTableFQN], 20 LastDDLTimestamp: lastDDLTimestamps[aoTableFQN], 21 } 22 } 23 24 return aoTableEntries 25 } 26 27 func getAllModCounts(connectionPool *dbconn.DBConn) map[string]int64 { 28 var segTableFQNs = getAOSegTableFQNs(connectionPool) 29 modCounts := make(map[string]int64) 30 for aoTableFQN, segTableFQN := range segTableFQNs { 31 modCounts[aoTableFQN] = getModCount(connectionPool, segTableFQN) 32 } 33 return modCounts 34 } 35 36 func getAOSegTableFQNs(connectionPool *dbconn.DBConn) map[string]string { 37 38 39 atLeast7Query := fmt.Sprintf(` 40 SELECT seg.aotablefqn, 41 'pg_aoseg.' || quote_ident(aoseg_c.relname) AS aosegtablefqn 42 FROM pg_class aoseg_c 43 JOIN (SELECT pg_ao.relid AS aooid, 44 pg_ao.segrelid, 45 aotables.aotablefqn 46 FROM pg_appendonly pg_ao 47 JOIN (SELECT c.oid, 48 quote_ident(n.nspname) || '.' || quote_ident(c.relname) AS aotablefqn 49 FROM pg_class c 50 JOIN pg_namespace n ON c.relnamespace = n.oid 51 JOIN pg_am a ON c.relam = a.oid 52 WHERE a.amname in ('ao_row', 'ao_column') 53 AND %s 54 ) aotables ON pg_ao.relid = aotables.oid 55 ) seg ON aoseg_c.oid = seg.segrelid`, relationAndSchemaFilterClause()) 56 57 query := atLeast7Query 58 59 results := make([]struct { 60 AOTableFQN string 61 AOSegTableFQN string 62 }, 0) 63 err := connectionPool.Select(&results, query) 64 gplog.FatalOnError(err) 65 resultMap := make(map[string]string) 66 for _, result := range results { 67 resultMap[result.AOTableFQN] = result.AOSegTableFQN 68 } 69 return resultMap 70 } 71 72 func getModCount(connectionPool *dbconn.DBConn, aosegtablefqn string) int64 { 73 74 // In GPDB 7+, the coordinator no longer stores AO segment data so we must 75 // query the modcount from the segments. Unfortunately, this does give a 76 // false positive if a VACUUM FULL compaction happens on the AO table. 77 atLeast7Query := fmt.Sprintf(`SELECT COALESCE(pg_catalog.sum(modcount), 0) AS modcount FROM gp_dist_random('%s')`, 78 aosegtablefqn) 79 80 query := atLeast7Query 81 82 var results []struct { 83 Modcount int64 84 } 85 err := connectionPool.Select(&results, query) 86 gplog.FatalOnError(err) 87 88 return results[0].Modcount 89 } 90 91 func getLastDDLTimestamps(connectionPool *dbconn.DBConn) map[string]string { 92 93 atLeast7Query := fmt.Sprintf(` 94 SELECT quote_ident(aoschema) || '.' || quote_ident(aorelname) as aotablefqn, 95 lastddltimestamp 96 FROM ( SELECT c.oid AS aooid, 97 n.nspname AS aoschema, 98 c.relname AS aorelname 99 FROM pg_class c 100 JOIN pg_namespace n ON c.relnamespace = n.oid 101 JOIN pg_am a ON c.relam = a.oid 102 WHERE a.amname in ('ao_row', 'ao_column') 103 AND %s 104 ) aotables 105 JOIN ( SELECT lo.objid, 106 MAX(lo.statime) AS lastddltimestamp 107 FROM pg_stat_last_operation lo 108 WHERE lo.staactionname IN ('CREATE', 'ALTER', 'TRUNCATE') 109 GROUP BY lo.objid 110 ) lastop 111 ON aotables.aooid = lastop.objid`, relationAndSchemaFilterClause()) 112 113 query := atLeast7Query 114 115 var results []struct { 116 AOTableFQN string 117 LastDDLTimestamp string 118 } 119 err := connectionPool.Select(&results, query) 120 gplog.FatalOnError(err) 121 resultMap := make(map[string]string) 122 for _, result := range results { 123 resultMap[result.AOTableFQN] = result.LastDDLTimestamp 124 } 125 return resultMap 126 }