A late reply: perhaps you could store the sort key as a string. Inserting a record between two existing rows can be done trivially by adding an additional character to a string, e.g. inserting "AM" between the rows "A" and "B". No reordering is required. A similar idea could be accomplished by using a floating point number or some simple bit arithmetic on a 4-byte integer: insert a row with a sort key value that is half way between the adjacent rows.
Pathological cases could arise where the string is too long, the float is too small, or there is no more room in the int, but then you could just renumber the entity and make a fresh start. A scan through and update of all your records on a rare occasion is much better than faulting every object every time a user reorders.
For example, consider int32. Using the high 3 bytes as the initial ordering gives you almost 17 million rows with the ability to insert up to 256 rows between any two rows. 2 bytes allows inserting 65000 rows between any two rows before a rescan.
Here's the pseudo-code I have in mind for a 2 byte increment and 2 bytes for inserting:
AppendRow:item
item.sortKey = tail.sortKey + 0x10000
InsertRow:item betweenRow:a andNextRow:b
item.sortKey = a.sortKey + (b.sortKey - a.sortKey) >> 1
Normally you would be calling AppendRow resulting in rows with sortKeys of 0x10000, 0x20000, 0x30000, etc. Sometimes you would have to InsertRow, say between the first and the second, resulting in a sortKey of 0x180000.