并发插入和更新postgres

时间:2016-04-20 15:06:33

标签: multithreading postgresql concurrency

当您在多线程环境中收到同一字段的并发插入和更新时,是否有办法解决问题。

示例

线程1

boost::multi_array<std::complex<double>, 3> SAP_max_combined_complex(boost::extents[1][1][1], boost::fortran_storage_order());

// Later in the code
SAP_max_combined_complex.resize(boost::extents[xDim][yDim][zDim]);
// The multi_array is populated correctly - this has been verified

mwSize numDims = SAP_max_combined_complex.num_dimensions();
mwSize outputSizes[3] = {SAP_max_combined_complex.shape()[0], SAP_max_combined_complex.shape()[1], SAP_max_combined_complex.shape()[2]};
mxArray* outputData = mxCreateNumericArray(numDims, outputSizes, mxDOUBLE_CLASS, mxCOMPLEX);
memcpy(mxGetData(outputData), (void*) SAP_max_combined_complex.data(), (sizeof(std::complex<double>) * SAP_max_combined_complex.num_elements()));

// I then write the mxArray to the file with
matPutVariable(mpMatFile, fieldName.toStdString().c_str(), outputData);

线程2

BEGIN 
insert into users (name,age) values('spiderman',27)
COMMIT

大部分时间更新(事务)都不知道插入发生因此它会抛出错误。

我在这里看到的是竞赛条件的经典例子,避免竞争条件的一种方法是使用效果锁。

如何对尚未存在于DB中的记录应用锁(记录)。

在上面的insert语句示例中,以便Update知道该记录不在DB中。

1 个答案:

答案 0 :(得分:0)

基于锁定的解决方案非常困难,可能不值得。您必须找到一种方法来创建一组数据,其中包含所有可能的名称&#39;字段,然后围绕该数据创建一个咨询锁定系统。它也可能容易出错。

但是,如果问题确实是UPDATEINSERT之后仍然有效,那么就会有更简单的解决方案。

具体来说,我想到的是:

BEGIN;
  SELECT count(*) FROM users WHERE name = 'spiderman';
  -- on the application side, check to see what the result is
  -- if it's 0, ROLLBACK
  -- if it's >0:
  UPDATE users SET age = 26 WHERE name = 'spiderman';
COMMIT;

如果你最终回滚,你会回来再试一次,这是否意味着像sleep这样简单的事情10秒并重新尝试,或者更复杂的事情就像将工作项放回队列并继续进行不同的工作。

如果您担心SELECTUPDATE之间发生的更新,可以SELECT FOR UPDATE,这将锁定所选行,直到您的交易完成为止。