You can, though cumbersome, do it. As bortzmeyer says , it is dangerous to rely on values from sequences that are contiguous, so it's best to leave it as it is if you can.
If you can not:
Every access to the table, which can lead to the fact that the row will have a specific name (i.e. each INSERT to this table), and if you allow (albeit carelessly) every UPDATE that can change the name ) should do this inside a transaction that first blocks soemthing . The simplest and least efficient option is to simply lock the entire table with LOCK users IN EXCLUSIVE MODE (adding the last three words allows parallel access for reading by other processes, which is safe).
However, this is a very crude lock that slows down performance if there are many simultaneous changes to users ; a better option would be to block one matching row in another table that should already exist. This row can be locked with SELECT ... FOR UPDATE . This only makes sense when working with a "child" table, which has an FK dependency on another "parent" table.
For example, imagine that we are actually trying to safely create new orders for a customer and that these orders somehow identify the "names". (I know a bad example ...) orders has an FK dependency on customers . Then, to prevent the creation of two orders with the same name for this customer, you can do the following:
BEGIN; -- Customer 'jbloggs' must exist for this to work. SELECT 1 FROM customers WHERE id = 'jbloggs' FOR UPDATE -- Provided every attempt to create an order performs the above step first, -- at this point, we will have exclusive access to all orders for jbloggs. SELECT 1 FROM orders WHERE id = 'jbloggs' AND order_name = 'foo' -- Determine if the preceding query returned a row or not. -- If it did not: INSERT orders (id, name) VALUES ('jbloggs', 'foo'); -- Regardless, end the transaction: END;
Please note: it’s not enough just to lock the corresponding row in users with SELECT ... FOR UPDATE - if the row does not exist yet, several simultaneous processes can simultaneously indicate that the row does not exist, and then try to perform simultaneous inserts, which leads to unsuccessful transactions and therefore sequence gaps.
Any locking scheme will work; The important thing is that anyone trying to create a string with the same name should try to lock the same object .
j_random_hacker
source share