I've been having some talks on #prolog about the best way to implement effects in logic programming languages and have come across some really good information, due in large part to "ski" who hangs out on #prolog.
There seem to be quite a few ways to implement effects for I/O. I'm not sure exactly at this point how many of them will be appropriate to implementing non-monotonic logic, by which I mean allowing the data store to grow/shrink.
Apparently the Monad strategy can move into the logic programming scene without too much difficulty. There are even a few papers about using monads in lambda-prolog that I've come across lately. This method has a lot going for it, as it seems to have worked fairly well in haskell and clean.
Another way is using linearity. This has a lot of appeal since linear logic has a well understood declarative semantics and it doesn't force us to use higher order constructs in order to achieve I/O. I'm not sure how this would interact with changing the data store though.
Mercury uses the linearity approach. First we declare the main predicate to be of a determinate mode, meaning that there is no way that we can have other choices. now the I/O resource is exhausted when used and we don't have to worry about backtracking over the use of the resource.
All of this new information makes the end goal of a fully declarative system where effects can take place seem more feasible.