diff --git a/neo/lib/interfaces.py b/neo/lib/interfaces.py
index 35b05ceab90b2ff4336c4629efd67f291d3dcdcc..761c983b3d2c56838d21eba59d198457d3a74635 100644
--- a/neo/lib/interfaces.py
+++ b/neo/lib/interfaces.py
@@ -74,7 +74,7 @@ def implements(obj, ignore=()):
         assert not wrong_signature, wrong_signature
     return obj
 
-def _set_code(func):
+def _stub(func):
     args, varargs, varkw, _ = inspect.getargspec(func)
     if varargs:
         args.append("*" + varargs)
@@ -82,16 +82,25 @@ def _set_code(func):
         args.append("**" + varkw)
     exec "def %s(%s): raise NotImplementedError\nf = %s" % (
         func.__name__, ",".join(args), func.__name__)
-    func.func_code = f.func_code
+    return f
 
 def abstract(func):
-    _set_code(func)
-    func.__abstract__ = 1
-    return func
+    f = _stub(func)
+    f.__abstract__ = 1
+    f.__defaults__ = func.__defaults__
+    f.__doc__ = func.__doc__
+    return f
 
 def requires(*args):
     for func in args:
-        _set_code(func)
+        # Tolerate useless abstract decoration on required method (e.g. it
+        # simplifies the implementation of a fallback decorator), but remove
+        # marker since it does not need to be implemented if it's required
+        # by a method that is overridden.
+        try:
+            del func.__abstract__
+        except AttributeError:
+            func.__code__ = _stub(func).__code__
     def decorator(func):
         func.__requires__ = args
         return func
diff --git a/neo/storage/database/importer.py b/neo/storage/database/importer.py
index 091dc454c8e40f6070beb353ddc1f647a8ab9111..e329f045ab6ef0d54009367095f5aa4844db5450 100644
--- a/neo/storage/database/importer.py
+++ b/neo/storage/database/importer.py
@@ -33,7 +33,7 @@ from ZODB.FileStorage import FileStorage
 
 from ..app import option_defaults
 from . import buildDatabaseManager, DatabaseFailure
-from .manager import DatabaseManager
+from .manager import DatabaseManager, Fallback
 from neo.lib import compress, logging, patch, util
 from neo.lib.interfaces import implements
 from neo.lib.protocol import BackendNotImplemented, MAX_TID
@@ -692,6 +692,9 @@ class ImporterDatabaseManager(DatabaseManager):
     def _fetchObject(*_):
         raise AssertionError
 
+    getLastObjectTID = Fallback.getLastObjectTID.__func__
+    _getDataTID = Fallback._getDataTID.__func__
+
     def getObjectHistory(self, *args, **kw):
         raise BackendNotImplemented(self.getObjectHistory)
 
diff --git a/neo/storage/database/manager.py b/neo/storage/database/manager.py
index 4ac10e0a735712c73a434c37bb5368d3e6f50052..8d439cc4f5ea6a31cc22d068655dfa28425a5c78 100644
--- a/neo/storage/database/manager.py
+++ b/neo/storage/database/manager.py
@@ -26,22 +26,9 @@ from . import DatabaseFailure
 
 READABLE = CellStates.UP_TO_DATE, CellStates.FEEDING
 
-def lazymethod(func):
-    def getter(self):
-        cls = self.__class__
-        name = func.__name__
-        assert name not in cls.__dict__
-        setattr(cls, name, func(self))
-        return getattr(self, name)
-    return property(getter, doc=func.__doc__)
-
 def fallback(func):
-    def warn(self):
-        logging.info("Fallback to generic/slow implementation of %s."
-            " It should be overridden by backend storage (%s).",
-            func.__name__, self.__class__.__name__)
-        return func
-    return lazymethod(wraps(func)(warn))
+    setattr(Fallback, func.__name__, func)
+    return abstract(func)
 
 def splitOIDField(tid, oids):
     if len(oids) % 8:
@@ -52,6 +39,9 @@ def splitOIDField(tid, oids):
 class CreationUndone(Exception):
     pass
 
+class Fallback(object):
+    pass
+
 class DatabaseManager(object):
     """This class only describes an interface for database managers."""
 
@@ -493,6 +483,7 @@ class DatabaseManager(object):
                 None if data_serial is None else util.p64(data_serial))
 
     @fallback
+    @requires(_getObject)
     def _fetchObject(self, oid, tid):
         """Specialized version of _getObject, for replication"""
         r = self._getObject(oid, tid)
@@ -738,6 +729,7 @@ class DatabaseManager(object):
             return self._pruneData(data_id_list)
 
     @fallback
+    @requires(_getObject)
     def _getDataTID(self, oid, tid=None, before_tid=None):
         """
         Return a 2-tuple: