Dies scheint zu funktionieren:
WITH sl AS (
SELECT plain_number FROM pool ORDER BY random() LIMIT 1 FOR UPDATE SKIP LOCKED
),
fu AS (
SELECT plain_number FROM pool WHERE NOT EXISTS(SELECT 1 FROM sl) ORDER BY random() LIMIT 1 FOR UPDATE
)
SELECT * FROM sl FULL JOIN fu USING (plain_number);
Aber es wartet eine zufällige plain_number
seine Verriegelung zu lösen. Ich glaube nicht, dass es möglich ist, auf die Freigabe der ersten Sperre zu warten.
Setup:
create table pool(
plain_number text primary key
);
insert into pool(plain_number)
select generate_series(1, 9)::text;
Und hier ist ein wenig node.js Skript, das ich für den Test geschrieben:
const pg = require("pg");
const options = {
"user": "test",
"password": "test",
"database": "test"
};
function thread_ish() {
const client = new pg.Client(options);
const end = client.end.bind(client);
const rollback = function (client) {
client.query("ROLLBACK", end);
};
client.connect(function() {
client.query("BEGIN", function (err) {
if (err) {
console.error(err);
return rollback(client);
}
client.query(
"WITH sl AS ("
+ " SELECT plain_number FROM pool ORDER BY random() LIMIT 1 FOR UPDATE SKIP LOCKED"
+ "), fu AS ("
+ " SELECT plain_number FROM pool WHERE NOT EXISTS(SELECT 1 FROM sl) ORDER BY random() LIMIT 1 FOR UPDATE"
+ ")"
+ "SELECT * FROM sl FULL JOIN fu USING (plain_number)",
function (err, result) {
if (err) {
console.error(err);
return rollback(client);
}
console.log("Selected number is", result.rows);
setTimeout(function() {
client.query("COMMIT", end);
}, 1000);
}
);
});
});
}
for (var i = 0; i < 13; ++i) {
setTimeout(thread_ish, Math.random() * 100);
}
Unrelated, aber: [ 'ORDER BY random()' wirklich schlecht] (http://StackOverflow.com/questions/8674718/best-way-to-select-random-rows-postgresql) – pozs
Dieses * kann * lösbar sein mit [CTEs] (https://www.postgresql.org/docs/ current/static/queries-with.html), aber ich bin mir nicht sicher: Die [FOR UPDATE SKIP LOCKED] -Dokumente (https://www.postgresql.org/docs/current/static/sql-select.html # SQL-FOR-UPDATE-SHARE) nicht erwähnt sie explizit, nur die Sub-Selects werden erwähnt (also, syntaxweise sollte es auch in CTEs akzeptiert werden). – pozs