Your second method is probably the best approach. However, you didn't ask what the "best approach" was or mention any specific problem you are encountering outside of concurrency, but rather:
What are other methods I can use ?
"Row number" for an order is not really a necessity for uniqueness in your database. When an order is displayed, the row order may or may not matter. If you abstract out the concept of a "row number" in your table, you get more options:
Row number of the table (not the sale) would guarantee uniqueness while allowing your RDBMS to manage concurrency in most cases (like AUTOINCREMENT on MySQL). If you need a "row number" you could write code to assign the number after the insert - and then return the results.
Add another key (like userId) to your key structure. Might be helpful for audit purposes, but mostly two users can't have the same ID, so it would guarantee that even if the "row number" was identical, the key is not. However, then a sale may have duplicate "row numbers", so they really aren't "row numbers" but rather the "sequence that a user entered products for this sale." Most of the time the "row numbers" would sequential, but there would be exceptions... ugly.
A nonce - "number used once" - using a hash algorithm would assign truly unique ID's, but it's not very useful in any other way (i.e. it is not ordered).
If you are also looking for database specific solutions, some of them will support "Triggers" or other custom code that you can use to manage the numbering for you (like the "autoincrement" option I mentioned above; but Oracle or MS SQL have other more complex functions/features).