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

Confirm that wp_session garbage collection is working correctly #2031

Closed
pippinsplugins opened this issue Feb 17, 2014 · 21 comments
Closed

Confirm that wp_session garbage collection is working correctly #2031

pippinsplugins opened this issue Feb 17, 2014 · 21 comments
Labels
Milestone

Comments

@pippinsplugins
Copy link
Contributor

It seems that the wp_session garbage collection isn't working correctly. I've seen numerous reports of sites having thousands and thousands, or millions even, rows in wp_options related to wp_session.

Every wp_session row should expire and get automatically cleaned out via a cron job that runs twice a day. As far as I can tell, however, the cron is never firing.

@spencerfinnell
Copy link
Contributor

@pippinsplugins Did you find out of the cron is being run? We just had a report of this as well.

@pippinsplugins
Copy link
Contributor Author

As far as I can tell it's running.

@pippinsplugins pippinsplugins modified the milestones: 1.9.9, 1.9.6 Apr 15, 2014
@pippinsplugins
Copy link
Contributor Author

Seems this still isn't working. I still see reports of thousands upon thousands of rows in wp_options.

@sunnyratilal sunnyratilal reopened this Apr 15, 2014
@spencerfinnell
Copy link
Contributor

Is it the standard transient cron that's supposed to run or something else registered by the sessions class?

@pippinsplugins
Copy link
Contributor Author

WP Session doesn't use transients. This is what is supposed to run: https://github.com/easydigitaldownloads/Easy-Digital-Downloads/blob/master/includes/libraries/wp-session.php#L118

@pippinsplugins pippinsplugins modified the milestones: 2.0, 1.9.9 May 2, 2014
@cklosowski
Copy link
Contributor

Here's the query count for wp-push :/ deff something going on:
SELECT count(*) FROM wp_options WHERE option_name LIKE '_wp_session_expires_%'; count(*) 18378

@cklosowski
Copy link
Contributor

I think the issue is related to the option_value...check this one entry out:
46018 _wp_session_expires_d5aa59c520fbc115aa77f00580c05efa 2778971534 no

The timestamp on that: 2778971534 is GMT: Wed, 23 Jan 2058 00:32:14 GMT

@pippinsplugins
Copy link
Contributor Author

Whoa, so looks like the expiration date is getting set really far in the future.

pippinsplugins added a commit that referenced this issue May 18, 2014
@pippinsplugins
Copy link
Contributor Author

I just discovered that we were modifying the expiration time but not the expiration variant. This is how Eric explains the two values:

    /**
     * Set both the expiration time and the expiration variant.
     *
     * If the current time is below the variant, we don't update the session's expiration time. If it's
     * greater than the variant, then we update the expiration time in the database.  This prevents
     * writing to the database on every page load for active sessions and only updates the expiration
     * time if we're nearing when the session actually expires.
     *
     * By default, the expiration time is set to 30 minutes.
     * By default, the expiration variant is set to 24 minutes.
     *
     * As a result, the session expiration time - at a maximum - will only be written to the database once
     * every 24 minutes.  After 30 minutes, the session will have been expired. No cookie will be sent by
     * the browser, and the old session will be queued for deletion by the garbage collector.
     *
     * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data.
     * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions.
     */
    protected function set_expiration() {
        $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 );
        $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
    }

We had the expiration set to 24 hours but the variant was still set to 24 minutes.

@pippinsplugins
Copy link
Contributor Author

@cklosowski I just confirmed the expiration bug as well. I created a brand new session and the expiration was also set to 2058.

@pippinsplugins
Copy link
Contributor Author

Found it! WP Session sets the expiration like this:

protected function set_expiration() {
    $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 );
    $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
}

We modify the expiration to be 24/23 hours by doing this:

add_filter( 'wp_session_expiration_variant', array( $this, 'set_expiration_variant_time' ), 99999 );
add_filter( 'wp_session_expiration', array( $this, 'set_expiration_time' ), 99999 );

.
.
.
.

/**
 * Force the cookie expiration variant time to 23 hours
 *
 * @access public
 * @since 2.0
 * @param int $exp Default expiration (1 hour)
 * @return int
 */
public function set_expiration_variant_time( $exp ) {
    return current_time( 'timestamp' ) + ( 30 * 60 * 23 );
}

/**
 * Force the cookie expiration time to 24 hours
 *
 * @access public
 * @since 1.9
 * @param int $exp Default expiration (1 hour)
 * @return int
 */
public function set_expiration_time( $exp ) {
    return current_time( 'timestamp' ) + ( 30 * 60 * 24 );
}

WP Session takes time() + the number of seconds set in the expiration filter. We were giving WP Session a timestamp of current time + 24 hours. The two timestamps were getting added together, resulting in HUGE expirations.

@pippinsplugins
Copy link
Contributor Author

This bug has resulted in a TON of session rows not getting properly cleared out, which can have some significant impacts on performance for some sites. I think we should do our best to clear these out during the EDD 2.0 upgrade routine.

My proposal is that we run an SQL query to delete all sessions that have an expiration less than May 28, 2058 (a day or two before EDD 2.0 goes out). Unless someone has manually modified the session expiration dates (I'm pretty sure no one has), all recently set sessions (over the last few months) will have an expiration date of 2058. As long as we don't delete any session created 24 hours before the upgrade routine, it shouldn't cause any issues.

I just ran a quick test on the EDD site to see how many session rows there are that have an expiration less than May 15, 2058:

SELECT * FROM `edd_options` WHERE option_name LIKE '_wp_session_expires_%' AND option_value+0 < 2788703418

There were 4566 rows found.

@pippinsplugins
Copy link
Contributor Author

This seems to do the trick nicely:

$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%' AND option_value+0 < 2789308218" );

@pippinsplugins
Copy link
Contributor Author

Closing as fixed. If there are any concerns or issues, please re-open.

@pippinsplugins
Copy link
Contributor Author

I suck and failed to actually fix the expirations dates :P

@pippinsplugins pippinsplugins reopened this Jun 7, 2014
@pippinsplugins pippinsplugins modified the milestones: 2.0.1, 2.0 Jun 7, 2014
@pippinsplugins
Copy link
Contributor Author

Nevermind, it was due to having an old cookie still stored.

@pippinsplugins pippinsplugins modified the milestones: 2.0.1, 2.0 Jun 7, 2014
@bdurette
Copy link

I think the upgrade function needs to delete options that are > some value, not <.

@cklosowski
Copy link
Contributor

@bdurette Just as a heads up, we created a plugin to help with this recently:
https://github.com/easydigitaldownloads/edd-session-cleanup

It does 3 types of cleanup.

@ghinaaltal
Copy link

hello guys,

please can anyone help me!
I am the admin of a new website that is still new and have no post or news, the website is hosted on Linux, Ubuntu server. I noticed lately that the data base of the website is increasing rapidly day by day without performing any thing on the site..
and the wp_options table is full of this records:

_wp_session_expires_71d531600d0bdfdde3f08b1f580c5c7b

_wp_session_9998b4cdeb00519b1bced28c43702bef
_wp_session_expires_9998b4cdeb00519b1bced28c43702bef
_wp_session_ffe442604b947bb0893a03d3d7d70c73
_wp_session_41f9a4c1866351f75cef324c80014899
_wp_session_expires_ffe442604b947bb0893a03d3d7d70c73
_wp_session_expires_41f9a4c1866351f75cef324c80014899
_wp_session_9735cdb65c9e46c6a7e54ddefd76f0a7
_wp_session_expires_9735cdb65c9e46c6a7e54ddefd76f0a7
_wp_session_2530eafcd5d0790982c17f4d6c02500b
_wp_session_expires_2530eafcd5d0790982c17f4d6c02500b
_wp_session_590b5fca3e1b057511f5b0822edb969e
_wp_session_expires_590b5fca3e1b057511f5b0822edb969e
_wp_session_7b8d8eda21fe050e1067627a50c58571
_wp_session_expires_7b8d8eda21fe050e1067627a50c58571

how can I solved this issue, I highly appreciate any help there..
and please to show me in details how to solve it as am new in websites

@pippinsplugins
Copy link
Contributor Author

@ghinaaltal you can use PHP sessions instead by adding this to your wp-config.php:

define( 'EDD_USE_PHP_SESSIONS', true );

The session rows should be automatically deleted each day when the expire. If that is not happening, please make sure your wp-cron is working properly.

@ghinaaltal
Copy link

@pippinsplugins thank you I will try adding define( 'EDD_USE_PHP_SESSIONS', true ); to wp_config file..
but do you have any idea why a huge number of this session is created in this shot time? even though the site is new and has no traffic on it..

Also it seems that wp_session_garbage_collection cron job is not working properly, how can I fix that please??

Thanks in advanced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants