  Serializability is a well-understood concurrency control mechanism that eases
reasoning about highly-concurrent database programs. Unfortunately, enforcing
serializability has a high-performance cost, especially on geographically
distributed database clusters. Consequently, many databases allow programmers
to choose when a transaction must be executed under serializability, with the
expectation that transactions would only be so marked when necessary to avoid
serious concurrency bugs. However, this is a significant burden to impose on
developers, requiring them to (a) reason about subtle concurrent interactions
among potentially interfering transactions, (b) determine when such
interactions would violate desired invariants, and (c) then identify the
minimum number of transactions whose executions should be serialized to prevent
these violations. To mitigate this burden, in this paper we present a sound and
fully automated schema refactoring procedure that transforms a program's data
layout -- rather than its concurrency control logic -- to eliminate statically
identified concurrency bugs, allowing more transactions to be safely executed
under weaker and more performant database guarantees. Experimental results over
a range of database benchmarks indicate that our approach is highly effective
in eliminating concurrency bugs, with safe refactored programs showing an
average of 120% higher throughput and 45% lower latency compared to the
baselines.
