Expanded "Health Center"

Expanded "Health Center"

by Braden MacDonald -
Number of replies: 7
I needed an easy way to solve the problems I have having with invalid database entries breaking the gradebook, and I noticed the "health center" file /admin/health.php .
  • I added a new function in health.php called health_find_duplicates(...) that makes it really easy to search for duplicate entries in any given table.
  • I added 5 new problem tests to the health center, mostly focused on repairing problems with the gradebook.
  • The health center is now capable of recovering a database from the problems described in MDL-10636 ("found more than one record in fetch()!")
  • I have not tested this very extensively, and I don't know if it will work with databases other than MySQL. However, it "works for me".
If any of this interests you, I've attached the updated health.php to this post. Let me know what you think, and what works or not for you.
Average of ratings: Useful (1)
In reply to Braden MacDonald

Re: Expanded "Health Center"

by Martín Langhoff -
Interesting! What's the DB cost? # of queries on a very large site?

Tried to read the file, but it's hard to tell what you've changed. Unified diffs are much better to discussion of new code...
In reply to Martín Langhoff

Re: Expanded "Health Center"

by Braden MacDonald -
Sorry, I was coding this on a Windows box and didn't have a diff program installed. I've attached a patch to this post.

I really haven't tested it enough to say what the database cost is...

However, because I coded this out of necessity and with looming deadlines, I was aiming for a working, effective solution rather than an efficient solution - the SQL may need optimizing.

If the "health center" idea takes off and becomes more than a hidden but helpful feature of the administration panel, we may have to consider changing some of the automatic tests into manual tests, so that the database is not hit too hard every time someone loads the health.php page. However, I don't think that's a concern for the moment; right now there are only 6 problem tests that query the database, 5 of which I just added.
In reply to Braden MacDonald

Re: Expanded "Health Center"

by Martín Langhoff -

Hi Braden -

thanks for the diff - now I see what you mean wink

I agree that they should be split out, but right now, in such a way that cheap/trivial checks can run right there, and expensive checks are in subpages. Otherwise we cannot include useful checks like yours.

If you are proposing you patch for inclusion, you must consider what happens in a moodle with 10K courses / 50K users.

And reading your patch, the checks need some perf tuning wink

  • All the WHERE NOT IN (subselect) are faster and scalable scalable with a LEFT OUTER JOIN ... WHERE xx.id IS NULL .

  • the find_duplicates() thing is pretty scary. Will work fine in our tiny "configuration" tables but it can easily bring everything down on a "data" table. Not entirely sure of the usage patterns in grade_items.

In reply to Martín Langhoff

Re: Expanded "Health Center"

by Braden MacDonald -
Thanks for the feedback, Martin. I'm new to SQL programming, and I don't have much experience with SQL optimization or very large Moodles.

I think that even if the database-intensive checks are split out, it is still more useful to an administrator if he can in one click initiate a comprehensive automatic analysis of the integrity of his database. What about moving the database checks to a separate page, health_db.php or something. The health.php page would then present a list of all the tests that could be run, with a checkbox next to each. When the user submits that form, all the checked tests will be run automatically. The health_db.php page would then do something like this:
$n = count($tests);
for ($i=0;$i<$n;$i++) {
if (!isset($_GET['run'.$i])) {
echo 'Skipping test '.$i.'...';
}
echo 'Test '.$i.'/'.$n.': Checking '.$tests[$i]->name.'...<br/>';
$tests[$i]->run(); // DB intensive
// You could even sleep() here, or break the loop
// if too many tests have found errors
}
for ($i=0;$i<$n;$i++) {
if ($tests[$i]->has_problem() /* read cached result */) {
echo 'Problem found.<br/>'.$tests[$i]->description();
echo 'link to fix just this one problem.';
}
}

That way, the administrator doesn't have to manually initiate numerous different tests individually just to know that there are no major database problems in any of the 10K courses on his Moodle.

As for the efficiency of the find_duplicates() function, I think you can make it less scary by checking each table in chunks. e.g.

$all_dupes = array();
foreach ($courses as $courseid) {
$dupes = health_find_duplicates('a_table', 'the_column_to_check', 'courseid='.$courseid);
foreach($dupes as $d) { $all_dupes[] = $d; }
}

Because doing this will only consider rows in the table WHERE courseid=x.

Anyhow, I don't really have the time right now to take this much further myself, but I wanted to throw the code out there in case anybody else finds it useful, or was stuck in the same situation I was with a horribly broken gradebook.
In reply to Braden MacDonald

Re: Expanded "Health Center"

by Larry Elchuck -
Braden

I also encountered the "Found more than one record in fetch() !" after backing up a 1.8 course and trying to install it on top of an older version of the same course on a 1.9.1 build. When restored the 1.8 backup as a new 1.9.1 course, I could create it ok.

When I used your version of the health.php on Moodle 1.9.1 (last night build), it detected errors as shown here. I used your built-in functionality to remove the errors but I still can not delete the courses that are messed up.

I continue to get "Found more than one record in fetch() !" during the deletion process and the course will not delete.

larry
fetch error


In reply to Larry Elchuck

Re: Expanded "Health Center"

by Thomas Bachert -
Would adding this Health Center give me the function of refreshing my quiz grades so they get pushed into the gradebook. I have a current issue in Moodle Tracker, MDL-18032, that consists of my running #mysqlcheck -u moodleuser -p --auto-repair moodle. I ran the repair code and now the only grades that appear in the gradebook are the ones that were added manually. From reading one of the developer pages there is suppose to be a process that passes grades to the gradebook. I believe it is the grade_get_grades code. Any help would be appreciated. Please provide as much details as possible.