Никогда не храните сериализованные объекты, доступ к ним медленный (поиск, десериализация), а поиск еще сложнее.
Если это сравнительно небольшое количество задач и они логические, вы можете хранить их как битовые маски (это может быть неправильный термин).
1 = first_login
2 = profile_complete
4 = other_thing_complete
8 = other_thing2_complete
16 = other_thing3_complete
...
Тогда значение 10 означает profile_complete + other_thing2_complete.
См. http://dev.mysql.com/doc/refman/5.0/en/bit-functions.html или поиск по ним.
mysql> select 10&2;
+------+
| 10&2 |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
mysql> select 10&8;
+------+
| 10&8 |
+------+
| 8 |
+------+
1 row in set (0.01 sec)
mysql> select 10&1;
+------+
| 10&1 |
+------+
| 0 |
+------+
1 row in set (0.00 sec)
mysql> select 10&4;
+------+
| 10&4 |
+------+
| 0 |
+------+
1 row in set (0.00 sec)
mysql> select 10&16;
+-------+
| 10&16 |
+-------+
| 0 |
+-------+
1 row in set (0.00 sec)
Как вы можете видеть, только первые два запроса вернули ненулевое значение, что означает, что если вы ищете записи, где поле anded с 8 не равно нулю, вы получите все записи, где other_thing2_complete завершено и т. д. Чтобы установить для other_thing2_complete значение true, просто добавьте 8. Для установки значения false для other_thing2_complete просто вычтите 8.
Никогда не делал этого сам, поэтому вы можете столкнуться с проблемами, которые я не предвидел. Но если все действия, которые вы отслеживаете, являются логическими, то это должно сработать и позволить лучший поиск / обновление.