Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dcrpg: Remove duplicates for votes, misses and treasury table #1979

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions db/dcrpg/indexing.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,18 @@ func (pgb *ChainDB) DeleteDuplicateAgendaVotes() (int64, error) {
return DeleteDuplicateAgendaVotes(pgb.db)
}

func (pgb *ChainDB) DeleteDuplicateVotes() (int64, error) {
return DeleteDuplicateVotes(pgb.db)
}

func (pgb *ChainDB) DeleteDuplicateMisses() (int64, error) {
return DeleteDuplicateMisses(pgb.db)
}

func (pgb *ChainDB) DeleteDuplicateTreasuryTxs() (int64, error) {
return DeleteDuplicateTreasuryTxs(pgb.db)
}

// Indexes checks

// MissingIndexes lists missing table indexes and their descriptions.
Expand Down
29 changes: 29 additions & 0 deletions db/dcrpg/internal/stakestmts.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,35 @@ const (
FROM agenda_votes) t
WHERE t.rnum > 1);`

// DeleteVotesDuplicateRows removes rows that would violate the unique
// index uix_votes_hashes_index. This should be run prior to creating the index.
DeleteVotesDuplicateRows = `DELETE FROM votes
WHERE id IN (SELECT id FROM (
SELECT id,
row_number() OVER (PARTITION BY tx_hash, block_hash ORDER BY id DESC) AS rnum
FROM votes) t
WHERE t.rnum > 1);`

Comment on lines +413 to +421
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been hitting this more often cuz I've had to drop my testnet dcrdata database and resync for both mainnet and testnet.

Got this log from mainnet dcrdata.

2024-08-22 21:27:40.740 [INF] PSQL: Indexing votes table on candidate block...
2024-08-22 21:28:01.216 [INF] PSQL: Indexing votes table on block hash...
2024-08-22 21:28:12.322 [INF] PSQL: Indexing votes table on block+tx hash...
2024-08-22 21:28:15.537 [ERR] DATD: dcrpg.SyncChainDB failed at height 898277.
2024-08-22 21:28:15.537 [INF] DATD: Shutdown requested. Shutting down...
2024-08-22 21:28:15.538 [DBG] JAPI: Got quit signal. Exiting block connected handler for STATUS monitor.
2024-08-22 21:28:15.539 [WRN] EXPR: ExchangeBot has quit.
2024-08-22 21:28:15.539 [DBG] DATD: Block prefetcher hits = 108, misses = 2.
2024-08-22 21:28:15.539 [INF] DATD: Gracefully shutting down web server...
2024-08-22 21:28:15.541 [INF] PUBS: Stopping websocket hub.
2024-08-22 21:28:15.541 [DBG] PUBS: Unregistered and killed 0 clients.
2024-08-22 21:28:15.541 [INF] EXPR: Stopping websocket hub.
2024-08-22 21:28:15.540 [ERR] XBOT: dcrdex websocket error: read tcp 192.168.1.243:58607->45.77.164.152:7232: use of closed network connection
2024-08-22 21:28:15.677 [DBG] SKDB: badger: Got compaction priority: {level:0 score:1.73 dropPrefixes:[]}
2024-08-22 21:28:16.381 [DBG] SKDB: badger: LOG Compact. Added 898280 keys. Skipped 1 keys. Iteration took: 701.425775ms
2024-08-22 21:28:16.836 [DBG] SKDB: badger: Discard stats: map[]
2024-08-22 21:28:16.859 [INF] SKDB: badger: LOG Compact 0->1, del 2 tables, add 1 tables, took 1.180893312s
2024-08-22 21:28:16.859 [DBG] SKDB: badger: Compaction for level: 0 DONE
2024-08-22 21:28:16.951 [INF] DATD: Closing connection to dcrd.
2024-08-22 21:28:16.952 [INF] DATD: Bye!
2024-08-22 21:28:17.203 [ERR] DATD: IndexAll failed: pq: could not create unique index "uix_votes_hashes_index"

// DeleteMissesDuplicateRows removes rows that would violate the unique
// index uix_misses_hashes_index. This should be run prior to creating the index.
DeleteMissesDuplicateRows = `DELETE FROM misses
WHERE id IN (SELECT id FROM (
SELECT id,
row_number() OVER (PARTITION BY ticket_hash, block_hash ORDER BY id DESC) AS rnum
FROM misses) t
WHERE t.rnum > 1);`

// DeleteTreasuryTxsDuplicateRows removes rows that would violate the unique
// index uix_treasury_tx_hash. This should be run prior to creating the index.
DeleteTreasuryTxsDuplicateRows = `DELETE FROM treasury
WHERE (tx_hash, block_hash) IN (SELECT tx_hash, block_hash FROM (
SELECT
tx_hash,
block_hash,
row_number() OVER (PARTITION BY tx_hash, block_hash) AS rnum
FROM treasury) t
WHERE t.rnum > 1);`

// Select

SelectAgendasVotesByTime = `SELECT votes.block_time AS timestamp,` +
Expand Down
36 changes: 36 additions & 0 deletions db/dcrpg/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,42 @@ func DeleteDuplicateAgendaVotes(db *sql.DB) (int64, error) {
return sqlExec(db, internal.DeleteAgendaVotesDuplicateRows, execErrPrefix)
}

// DeleteDuplicateVotes deletes rows in votes with duplicate tx_hash and
// block_hash leaving one row with the lowest id.
func DeleteDuplicateVotes(db *sql.DB) (int64, error) {
if isuniq, err := IsUniqueIndex(db, internal.IndexOfVotesTableOnHashes); err != nil && err != sql.ErrNoRows {
return 0, err
} else if isuniq {
return 0, nil
}
execErrPrefix := "failed to delete duplicate votes: "
return sqlExec(db, internal.DeleteVotesDuplicateRows, execErrPrefix)
}

// DeleteDuplicateMisses deletes rows in misses with duplicate ticket_hash and
// block_hash leaving one row with the lowest id.
func DeleteDuplicateMisses(db *sql.DB) (int64, error) {
if isuniq, err := IsUniqueIndex(db, internal.IndexOfMissesTableOnHashes); err != nil && err != sql.ErrNoRows {
return 0, err
} else if isuniq {
return 0, nil
}
execErrPrefix := "failed to delete duplicate misses: "
return sqlExec(db, internal.DeleteMissesDuplicateRows, execErrPrefix)
}

// DeleteDuplicateTreasuryTxs deletes rows in misses with duplicate tx_hash and
// block_hash leaving one row with the lowest id.
func DeleteDuplicateTreasuryTxs(db *sql.DB) (int64, error) {
if isuniq, err := IsUniqueIndex(db, internal.IndexOfTreasuryTableOnTxHash); err != nil && err != sql.ErrNoRows {
return 0, err
} else if isuniq {
return 0, nil
}
execErrPrefix := "failed to delete duplicate treasury txs: "
return sqlExec(db, internal.DeleteTreasuryTxsDuplicateRows, execErrPrefix)
}

// --- stake (votes, tickets, misses, treasury) tables ---

func InsertTreasuryTxns(db *sql.DB, dbTxns []*dbtypes.Tx, checked, updateExistingRecords bool) error {
Expand Down
9 changes: 9 additions & 0 deletions db/dcrpg/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ func (pgb *ChainDB) DeleteDuplicates(barLoad chan *dbtypes.ProgressBarLoad) erro

// Remove duplicate agenda_votes
{TableName: "agenda_votes", DropDupsFunc: pgb.DeleteDuplicateAgendaVotes},

// Remove duplicate votes
{TableName: "votes", DropDupsFunc: pgb.DeleteDuplicateVotes},

// Remove duplicate misses
{TableName: "misses", DropDupsFunc: pgb.DeleteDuplicateMisses},

// Remove duplicate treasury txs
{TableName: "treasury", DropDupsFunc: pgb.DeleteDuplicateTreasuryTxs},
}

var err error
Expand Down
Loading