decred / politeia

ISC License
110 stars 75 forks source link

politeiad: MySQL max placeholder limit hit. #1608

Closed lukebp closed 2 years ago

lukebp commented 2 years ago

The maximum number of placeholders that can be included in a MySQL query is 65,535 placeholders. This number corresponds to the maximum value of an uint16.

Example, the query below contains 3 placeholders.

SELECT k, v FROM kv WHERE k IN (?,?,?);

When retrieving the vote results for a proposal, two blobs are retrieved from the key-value store for every vote that was cast. A blob for the vote itself and a blob that we refer to as a vote collider. The vote collider is a fail safe mechanism that causes a vote to fail at the tlog level if the dcr ticket has already been used to cast a previous vote and was not caught by the cast vote validation due to a bug or some other reason.

The recent subsidy split proposal had the highest voter participation rate yet and ran into this placeholder limit. Once the vote surpassed 32,767 votes, the vote results endpoint, which fetches all cast vote blobs and vote collider blobs from the key-value store, started running into the MySQL max placeholders limit and the vote results route would return an error.

Clients, such as politeiavoter, prepare votes before sending them to the server by fetching the vote results and filtering out any of their tickets that have already been cast. During the last ~25 hours of the vote, this process would error out due to the vote results endpoint not working properly. This prevented clients from voting if they had waited until the last ~25 hours to cast their votes or to start their politeiavoter trickler.

The server still accepted votes during this period that were being trickled in via politeiavoter clients that had started the trickling process prior to the last ~25 hours.