[ticket/15294] Another approach, optimize updating & purging expired sessions

PHPBB3-15294
This commit is contained in:
rxu 2019-11-03 23:14:52 +07:00
parent e9fc3ed22e
commit 46a68d37ee
No known key found for this signature in database
GPG key ID: 955F0567380E586A

View file

@ -959,48 +959,47 @@ class session
$this->time_now = time(); $this->time_now = time();
} }
// Firstly, delete guest sessions // Get expired sessions, only most recent for each registered user
$sql = 'DELETE FROM ' . SESSIONS_TABLE . ' // Inner SELECT gets most recent expired sessions data for unique session_user_id
WHERE session_user_id = ' . ANONYMOUS . ' // Outer SELECT gets also session_page for them
AND session_time < ' . (int) ($this->time_now - $config['session_length']); $sql_select = '(
$db->sql_query($sql); SELECT s1.session_page, s1.session_user_id, s1.session_time AS recent_time
// Get expired sessions, only most recent for each user
// Inner SELECT gets most recent expired sessions for unique session_user_id
// Outer SELECT gets session_page for them
$sql = 'SELECT s1.session_page, s1.session_user_id, s1.session_time AS recent_time
FROM ' . SESSIONS_TABLE . ' AS s1 FROM ' . SESSIONS_TABLE . ' AS s1
INNER JOIN ( INNER JOIN (
SELECT session_user_id, MAX(session_time) AS recent_time SELECT session_user_id, MAX(session_time) AS recent_time
FROM ' . SESSIONS_TABLE . ' FROM ' . SESSIONS_TABLE . '
WHERE session_time < ' . ($this->time_now - (int) $config['session_length']) . ' WHERE session_time < ' . ($this->time_now - (int) $config['session_length']) . '
AND session_user_id <> ' . ANONYMOUS . '
GROUP BY session_user_id GROUP BY session_user_id
) AS s2 ) AS s2
ON s1.session_user_id = s2.session_user_id ON s1.session_user_id = s2.session_user_id
AND s1.session_time = s2.recent_time'; AND s1.session_time = s2.recent_time
$result = $db->sql_query($sql); ) AS s3';
$del_user_id = array(); // Update user session data from above selected result
switch ($db->get_sql_layer())
while ($row = $db->sql_fetchrow($result))
{ {
$sql = 'UPDATE ' . USERS_TABLE . ' case 'sqlite3':
SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' case 'mysqli':
WHERE user_id = " . (int) $row['session_user_id']; $sql = 'UPDATE ' . USERS_TABLE . " AS u,
$db->sql_query($sql); $sql_select
SET u.user_lastvisit = s3.recent_time, u.user_lastpage = s3.session_page
WHERE u.user_id = s3.session_user_id";
break;
$del_user_id[] = (int) $row['session_user_id']; default:
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_lastvisit = s3.recent_time, user_lastpage = s3.session_page
FROM $sql_select
WHERE user_id = s3.session_user_id";
break;
} }
$db->sql_freeresult($result); $db->sql_query($sql);
if (count($del_user_id)) // Delete all expired sessions
{ $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
// Delete expired sessions WHERE session_time < ' . ($this->time_now - $config['session_length']);
$sql = 'DELETE FROM ' . SESSIONS_TABLE . ' $db->sql_query($sql);
WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . '
AND session_time < ' . ($this->time_now - $config['session_length']);
$db->sql_query($sql);
}
// Update gc timer // Update gc timer
$config->set('session_last_gc', $this->time_now, false); $config->set('session_last_gc', $this->time_now, false);