Merge pull request #890 from TheSerapher/issue-886

[IMPROVED] Use limits for DELETE statements
This commit is contained in:
Sebastian Grewe 2013-12-11 04:36:05 -08:00
commit 666a9ccc4a
2 changed files with 91 additions and 17 deletions

View File

@ -171,22 +171,41 @@ class Share Extends Base {
* @return return bool true or false
**/
public function purgeArchive() {
// Fallbacks if unset
if (!isset($this->config['purge']['shares'])) $this->config['purge']['shares'] = 25000;
if (!isset($this->config['purge']['sleep'])) $this->config['purge']['sleep'] = 1;
if ($this->config['payout_system'] == 'pplns') {
// Fetch our last block so we can go back configured rounds
$aLastBlock = $this->block->getLast();
// Fetch the block we need to find the share_id
$aBlock = $this->block->getBlock($aLastBlock['height'] - $this->config['archive']['maxrounds']);
// Now that we know our block, remove those shares
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE)");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage']) && $stmt->execute())
return true;
$affected = 1;
while ($affected > 0) {
// Sleep first to allow any IO to cleanup
sleep($this->config['purge']['sleep']);
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE) LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage']) && $stmt->execute()) {
$affected = $stmt->affected_rows;
} else {
return $this->sqlError();
}
}
} else {
// We are not running pplns, so we just need to keep shares of the past <interval> minutes
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE)");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute())
return true;
$affected = 1;
while ($affected > 0) {
// Sleep first to allow any IO to cleanup
sleep($this->config['purge']['sleep']);
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE) LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute()) {
$affected = $stmt->affected_rows;
} else {
return $this->sqlError();
}
}
}
return $this->sqlError();
return true;
}
/**
@ -197,11 +216,23 @@ class Share Extends Base {
* @return bool
**/
public function moveArchive($current_upstream, $block_id, $previous_upstream=0) {
$archive_stmt = $this->mysqli->prepare("
INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty)
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM $this->table
WHERE id > ? AND id <= ?");
if ($this->config['payout_system'] != 'pplns') {
// We don't need archived shares that much, so only archive as much as configured
$sql = "
INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty)
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM $this->table
WHERE id > ? AND id <= ?
AND time >= DATE_SUB(now(), INTERVAL " . $this->config['archive']['maxage'] . " MINUTE)";
} else {
// PPLNS needs archived shares for later rounds, so we have to copy them all
$sql = "
INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty)
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM $this->table
WHERE id > ? AND id <= ?";
}
$archive_stmt = $this->mysqli->prepare($sql);
if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute())
return true;
return $this->sqlError();
@ -214,11 +245,25 @@ class Share Extends Base {
* @return bool true or false
**/
public function deleteAccountedShares($current_upstream, $previous_upstream=0) {
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ?");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute())
return true;
return $this->sqlError();
// Fallbacks if unset
if (!isset($this->config['purge']['shares'])) $this->config['purge']['shares'] = 25000;
if (!isset($this->config['purge']['sleep'])) $this->config['purge']['sleep'] = 1;
$affected = 1;
while ($affected > 0) {
// Sleep first to allow any IO to cleanup
sleep($this->config['purge']['sleep']);
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ? LIMIT " . $this->config['purge']['shares']);
$start = microtime(true);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute()) {
$affected = $stmt->affected_rows;
} else {
return $this->sqlError();
}
}
return true;
}
/**
* Set/get last found share accepted by upstream: id and accounts
**/

View File

@ -215,6 +215,35 @@ $config['block_bonus'] = 0;
**/
$config['payout_system'] = 'prop';
/**
* Round purging
*
* Explanation:
* As soon as a round is finished, shares of that rate are archived (see below)
* and deleted from the `shares` table. Due to a large amount of shares in a
* single round, this can take a very long time. To reduce server load and allow
* other systems to access the DB during this high-load time, the DELETE
* calls are being limited to a number of rows. Then the process sleeps and
* continues to delete shares until all shares have been purged.
*
* You can adjust some purging settings here in order to improve your overall
* site performance during round ends. Keep in mind that drecreasing shares/time
* will make the cron run longer but at least keeps your site active. Vice versa
* higher numbers allow for a faster deletion but might affect the live site.
*
* This system is also used when purging archived shares.
*
* Available Options:
* sleep : Time to sleep between delete calls
* shares : How many shares to delete at one time
*
* Default:
* sleep : 5 seconds
* shares : 500000
**/
$config['purge']['sleep'] = 1;
$config['purge']['shares'] = 25000;
/**
* Archiving configuration for debugging
*