我们在应用程序中有一些持久数据,从服务器查询然后存储在数据库中,以便我们可以跟踪其他信息.因为我们不想查询何时在内存中使用对象,select for update所以我们会这样做,以便阻止其他想要获取相同数据的线程.
我不知道如何select for update处理不存在的行.如果该行不存在而另一个线程尝试select for update在同一行上执行另一个线程,则该线程是否会被阻塞,直到另一个事务完成或者它是否也会得到一个空的结果集?如果它只获得一个空的结果集是否有任何方法可以阻止它,例如通过立即插入缺失的行?
编辑:
因为有一个评论,我们可能会锁定太多,这里有一些关于我们案例中具体用法的更多细节.在减少的伪代码中,我们的程序流程如下所示:
d = queue.fetch();
r = SELECT * FROM table WHERE key = d.key() FOR UPDATE;
if r.empty() then
r = get_data_from_somewhere_else();
new_r = process_stuff( r );
if Data was present then
update row to new_r
else
insert new_r
Run Code Online (Sandbox Code Playgroud)
此代码在多个线程中运行,从队列中提取的数据可能与数据库中的同一行有关(因此锁定).但是,如果多个线程正在使用需要相同行的数据,则需要对这些线程进行顺序化(顺序无关紧要).但是,如果该行不存在,则此顺序化将失败,因为我们没有获得锁定.
编辑:
现在我有以下解决方案,这对我来说似乎是一个丑陋的黑客.
select the data for update
if zero rows match then
insert some dummy data // this will block if multiple transactions try to insert
if insertion failed then
// somebody beat us at the race
select the data for update
do processing
if data was changed then
update the old or dummy data
else
rollback the whole transaction
Run Code Online (Sandbox Code Playgroud)
我并非100%确定这实际上解决了这个问题,这个解决方案似乎也不是很好的风格.因此,如果任何人必须提供更多可用的东西,这将是伟大的.
Den*_*rdy 18
我不确定如何选择更新来处理不存在的行.
它没有.
如果您对新行有所了解,那么您可以做的最好的事情是使用咨询锁.(如果需要,使用hashtext(),并使用表的oid来锁定它.)
最好的事情是桌锁.
话虽如此,你的问题让你听起来比你应该更多地锁定方式.只在实际需要时锁定行,即写操作.