1

I'm bulk deleting posts from my WordPress site using the function wp_delete_post and categories using wp_delete_category. That are about 100.000 posts and 4.000 categories, and after a while I get a PHP Error

PHP Fatal error: Allowed memory size of ... bytes exhausted

That's what I do inside my code:

// get all IDs from the posts and categories
$delete_categories = $wpdb->get_col("SELECT DISTINCT(j.term_id)...");       
$delete_posts = $wpdb->get_col("SELECT DISTINCT(j.post_id)...");
$delete_parent_categories = $wpdb->get_col("SELECT tt.parent FROM $tbl_term_taxonomy tt ...");
// I removed the SQL statements for a better reading


foreach ($delete_posts as $dp) {
    echo "deleting post ".$dp."\n";
    wp_delete_post($dp, true);
    unset($dp);
}

unset($delete_posts);

foreach ($delete_categories as $dc) {
    echo "deleting category ".$dc."\n";
    wp_delete_category($dc);
    unset($dc);
}

unset($delete_categories);

foreach ($delete_parent_categories as $dc) {
    echo "deleting category ".$dc."\n";
    wp_delete_category($dc);
    unset($dc);
}

unset($delete_parent_categories);

Deleting the posts works, deleting some categories also works - but at some point the memory limit is exceeded and the script is terminated. Setting the memory limit to 1024MB doesn't look like a perfect solution for me.

Is there a way to free up the memory that the WordPress functions allocated?

  • This may not be a great idea but maybe loop like 500 (more or less) posts to be deleted at a time and then refresh the page. header("Refresh:0"); – deflime Aug 28 '17 at 8:19
  • I think that's not possible, because the script is a standalone script and runs without a webserver - so a header won't do anything here. – beeef Aug 28 '17 at 8:47
  • So put it into a WordPress page template or call it like any other php file. How are you getting it to run at the moment? – deflime Aug 28 '17 at 8:49
2

The code you use also uses WordPress functions that will first load posts (and other relevant data) in memory first and cache them using object cache. So, to delete 100.000 posts, your code will try to load each post in memory and that can take a lot of memory. I am not sure how high PHP memory is set in your case, but, you can either limit the deletion to 1000 or 5000 posts at once or increase PHP memory.

  • Can I manually clear the memory to free up space? Or should I repeatedly call the script as long as there are posts left and limit it to 5.000 posts per call? – beeef Aug 28 '17 at 9:55
  • 1
    Try to use 'wp_cache_flush()' function, it will clear the WordPress object cache. But, it is not a good idea to run it after each deletion, maybe call it after every 1000 posts deleted. – Milan Petrovic Aug 28 '17 at 9:58
  • Nice! Didn't know such a function exists. Thanks, I'll try that. – beeef Aug 28 '17 at 10:00
  • It is much better idea to delete such a large number of posts using only SQL queries. It would be a complex query with multiple joins (to delete posts, post meta, comments and any terms posts can have), but it will be fast, and no PHP memory issues. – Milan Petrovic Aug 28 '17 at 10:04
  • 1
    WordPress deletes from posts, postmeta (connect post.ID to postmeta.post_id), term_relationships (connect post.ID to term_relationship.object_id) and comments tables. And, after that, it has to run update for the terms counts. – Milan Petrovic Aug 28 '17 at 10:08
1

With so many posts to delete it is better to escape the limitations of the webserver and use wp-cli relevant example. The other alternative is to not use a live server, but to offload everything to your local development server, run your code there, and upload things back.

0

I recommend your first line of code be

wp_suspend_cache_addition( true );

This will stop the data from being added to the cache and bloat filling memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.