6

We have a lot of smart groups, and consequently a lot of deadlocks. There's already code in Civi that detects deadlock Exceptions, and then retries the query a few times. This is really helpful - I have extra logging on this, and I can see that it prevents a lot of errors. But this code doesn't kick in for people directly using the UI - they get the 'unknown error' yellow-screen-of-death immediately. This can happen on exports, or when opening complex groups. I dug into this and sort-of know why it's happening:

  • When a deadlock happens, an exception is thrown if $GLOBALS['_PEAR_default_error_options'][1] is set to 'exceptionHandler'. This exception triggers the code which retries the query.
  • An exception is not thrown if $GLOBALS['_PEAR_default_error_options'][1] is set to 'handle'.
  • $GLOBALS['_PEAR_default_error_options'][1] is set to 'exceptionHandler' when you generate smart groups via the API, and in most other circumstances
  • But $GLOBALS['_PEAR_default_error_options'][1] is set to 'handle' in the UI in general (?) - at least, it is on exports and when using 'Manage Groups'. So in this case no exception is raised. And if there's no exception, the try-catch blocks have nothing to work with and front-end users get 'unknown error' immediately.

I am happy to fund a fix for this, but I'm not sure what I'm getting myself into. Is this a bug, or is it an unfortunate consequence of how error handling needs to work for end users?

2
  • Can you share which CMS and which version of CiviCRM you are running? Commented Aug 27, 2018 at 13:37
  • WordPress and Civi 5.3.1 Commented Aug 28, 2018 at 19:46

1 Answer 1

1

Instead of trying to "hide" the problem when it happens, it might be safer/wiser to try to prevent it.

I like smartgroups and how powerful they are, but I found that it works better if I cache the results for a while (eg. a day) and rebuild the smart groups via the jobs.

Would it be acceptable to keep a "stalled" version of your groups for a while and avoid rebuilding them all the time in your case?

Also, you mention having a lot of smartgroups, it might be worthwhile creating a custom search that would run the queries you want when you need to use them instead of creating lots of smartgroups. We found it more performant and easier to maintain.

X+

5
  • We've done this to an extent, but we're heavy users of smart groups (well over 1000) and the staff make new ones every day. They would be quite confused / annoyed if their groups didn't update right away. We did some analysis of the most time consuming groups - as well as the 'base' groups that many others rely on - and turned these into regular groups that populate overnight. This helped a lot. To be honest I'm quite happy with the setup as it is: the deadlocks get caught and retried, and very rarely fail. It's just the UI deadlocks that are a difficulty. Commented Aug 28, 2018 at 20:00
  • I would be interested in how you analyzed the slowest smartgroups. We also experience deadlock problems with too many and too complex smartgroups Commented Aug 31, 2018 at 7:18
  • 1
    @RichardvanOosterhout we used a combination of two things. First we use New Relic monitoring, which lets us drill down into slow queries. Secondly I added basic time logging to Contact/BAO/GroupContactCache::load() - basically just starting a timer at the start of the function, stopping it at the end, and logging it along with the group ID. Quite revealing! Commented Sep 3, 2018 at 9:22
  • nice! would it be possible you can show me the code you inserted for that? Commented Sep 4, 2018 at 10:06
  • oops sorry - missed this. Email me at [email protected] and I'll send it over (just because it's not easy to put code in these comments) Commented Sep 14, 2018 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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