Node_access_rebuild needs tons of memory

ChrisKennedy - January 12, 2007 - 03:04
Project:Drupal
Version:5.x-dev
Component:node system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:closed
Description

node_access_build() requires a ton of memory when rebuilding the node_access table because it causes node_load() to load *every* node and keep them cached. On my site with 3800 nodes this easily swamped my 24MB of php memory. This patch tells node_load() not to cache the nodes.

AttachmentSizeStatusTest resultOperations
node_access_rebuild_0.patch642 bytesIgnoredNoneNone

#1

moshe weitzman - March 1, 2007 - 15:05
Status:needs review» reviewed & tested by the community

Dries have the exact same patch a +1 at http://drupal.org/node/123705. that one is a dupe of this one. Since Chris, Dries, and I all reviewed this, I set to RTBC.

#2

chx - March 4, 2007 - 21:48

While this is useful, this is not adequate to make this function usable. http://drupal.org/node/124727 . Note that this must be backported to 5.x .

#3

moshe weitzman - March 5, 2007 - 00:27

@chx - thats a nice feature, but lets not get in the way of this patch. You are overstating the issue when you say that this function is not usable. With this patch i was able to rebuild groups.drupal.org. Without the patch, I wasn't. This patch deserves to go in, and your comment just muddies the water, IMO.

#4

ChrisKennedy - March 5, 2007 - 16:38
Status:reviewed & tested by the community» fixed

Committed - http://drupal.org/cvs?commit=59253

#5

ChrisKennedy - March 5, 2007 - 16:39
Version:6.x-dev» 5.x-dev
Status:fixed» patch (to be ported)

Portable.

#6

chx - March 5, 2007 - 19:54

I am sorry if I muddled the waters -- my comment began with 'this is useful' and just wanted to draw attention to a related issue. groups.drupal.org is a rather small site btw in this context.

I am happy that my muddling have not stopped this issue from being committed and that's a good thing.

#7

drumm - March 7, 2007 - 03:30
Status:patch (to be ported)» fixed

COmmitted to 5.

#8

Anonymous - March 21, 2007 - 03:30
Status:fixed» closed

#9

jlmeredith - May 28, 2007 - 09:56
Priority:normal» minor
Status:closed» fixed

I may be wrong, but in the description for this bug, I believe that node_access_build() should be node_access_rebuild(). I hunted in the API docs for some time trying to find node_access_build(), lol to no avail. Just a minor change.

#10

ChrisKennedy - May 29, 2007 - 02:29
Priority:minor» normal
Status:fixed» closed

Yes, it was a typo and cannot be changed.

#11

sjs - May 15, 2008 - 16:15

I'm building a site with 80 000 nodes, and the node_access_rebuild_0.patch didn't seem to fix the problems I had with node_access_rebuild. So I wrote a command line script that does (see the attachment). It solves also the following problems:

The rebuild process takes several minutes (at least), and during that time most of the nodes get "permission denied" because of this line run:
db_query("DELETE FROM {node_access} where nid=%d",$node->nid);

So I made the script to delete "per node".

I also got around the php.ini time limit settings by calling the script from command line which has different php.ini than for apache2.

So.. its a bit of a hack, but it does the trick.

AttachmentSizeStatusTest resultOperations
node_access_rebuild.php_.txt2.3 KBIgnoredNoneNone

#12

enboig - June 13, 2008 - 22:43

My approach to a similar problem was creating a script which updates just one node each time and using javascript calls himself to update next node. The script is called rebuild_permissions.php:

<?php
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
user_authenticate('admin', 'admin');
$actual=db_result(db_query("SELECT nid FROM {node} WHERE nid > %d ORDER BY nid",$_GET['node']));
if (
$actual>0) {
$sencer=node_load($actual);
node_access_acquire_grants($sencer);
}
?>
<html>
<head>
<script type="text/javascript">
<!--
function delayer(){
   window.location = "rebuild_permissions.php?node=<?=$actual?>"
}
//-->
</script>
</head>
<body <?=($actual>0 ? " onLoad=\"setTimeout('delayer()', 500)\"" : "") ?>>
<?php
if ($actual>0) echo "doing...".$actual;
else echo
"Done";
?>

</body>
</html>

The output isn't necessary... But I like to know its working.
I already posted it in the mailing list, but I think it may be useful to other users.

#13

chris55 - December 4, 2008 - 11:46

I've been having the same problems and until we've got a server to support drupal 6 I decided on a quicker hack than sjs or enboig: i.e. when it happens, finish the job, don't start again. The code below is designed to be incorporated into a page (with php permissions) that only admins have access to and works with old versions of MySQL. It simply abstracts from the node_access_rebuild() function. If it fails to finish, it could be run again.

<?php
 
if (count(module_implements('node_grants'))) {
   
$result = db_query("SELECT n.nid FROM {node} as n left join {node_access} as a on n.nid=a.nid where a.nid is null");
   
$total = $granted= $left = 0;   
    while (
$node = db_fetch_object($result)) {
     
$total++;
     
$loaded_node = node_load($node->nid, NULL, TRUE);
      if (!empty(
$loaded_node)) {
       
node_access_acquire_grants($loaded_node);
       
$granted++;
      }
    }
 
$left= db_result(db_query("SELECT count(*) FROM {node} as n left join {node_access} as a on n.nid=a.nid where a.nid is null"),0);
 
drupal_set_message("granted $granted nodes from $total, $left left");
}
?>

Chris

#14

stieglitz - February 14, 2009 - 23:59

Thank you Chris for that most sweet script. I have been struggling with this issue for weeks thinking it was a problem with my Db or a configuration problem. The core permissions rebuilder looked as if it was working even though it hung for hours at 90%....after all the documentation said it could take a long time... I loved how easy it was to plug it in a page. I clicked preview and watched it click away! Totally awesome. Thanks again.
Jon

#15

mikhailian - March 18, 2009 - 19:02

#11
sjs - May 15, 2008 - 17:15

Simply beautiful! It is a shame your script is not included in the drupal scripts directory.

 
 

Drupal is a registered trademark of Dries Buytaert.