The solution, then, is not doing away with shared mutable state, as that's downright impossible, but with providing transactional semantics for that state. Once shared state has clear transactional semantics, the pure-functional nature of the programming language becomes secondary.
Let's imagine a programming language with perfect STM (i.e. an STM implementation that executes the most efficient code possible in every transaction). That language would have none of the problems described in the article, even if it were completely imperative. Hence, the problem is managing shared mutable state, and not existence of side-effects in general.
Pure functional programming could have been one solution to the problem, if only for the fact that it's not even a solution at all: Haskell programs still need a database. But the article assumes no other possible solutions, which is wrong. It focuses on one particular solution (which isn't even really a solution), rather than exploring many approaches. It is simply begging the question.
EDIT: I do agree that some partially-functional approaches are inherently dangerous, but I do not agree with the conclusion that the answer is going pure functional.
[1]: Except maybe for compilers, which is probably the most common complex software built in Haskell.