C++ MySQL选择更新,多线程超时

C++ MySQL选择更新,多线程超时,c++,mysql,database,transactions,timeout,C++,Mysql,Database,Transactions,Timeout,我在MySQL数据库中有一个表,其中包含一些“准备好的”作业 现在我有了一个C++1y多线程应用程序,其中每个线程都会转到表并选择一个状态为0(未完成)的作业,执行一些计算并在完成时设置状态为1 问题是许多线程将同时获取一个“作业行”,因此必须在数据库中进行一些锁定 锁定/更新/提交的C++方法是以下 connection = "borrow a connection from the pool" std::unique_ptr<sql::Statement> statement(c

我在MySQL数据库中有一个表,其中包含一些“准备好的”作业

现在我有了一个C++1y多线程应用程序,其中每个线程都会转到表并选择一个状态为0(未完成)的作业,执行一些计算并在完成时设置状态为1

问题是许多线程将同时获取一个“作业行”,因此必须在数据库中进行一些锁定

锁定/更新/提交的C++方法是以下

connection = "borrow a connection from the pool"
std::unique_ptr<sql::Statement> statement(connection->sql_connection_->createStatement());
connection->sql_connection_->setAutoCommit(false);


//statement->execute("START TRANSACTION");
std::unique_ptr<sql::ResultSet> rs(statement->executeQuery("select id from ww_jobs_for_update where status=0 ORDER BY id LIMIT 1 FOR UPDATE"));


if (rs->next()) {

  db_id = rs->getInt64(1);
  DEBUG << "Unlock Fetched: " << db_id;
}

rs->close();

std::stringstream ss;
ss << "update ww_jobs_for_update set status=1 where id=" << db_id;


statement->execute(ss.str());
//statement->execute("COMMIT;");
connection->sql_connection_->commit();

"release the connection to the pool();" 
connection=“从池中借用连接”
std::unique_ptr语句(connection->sql_connection->createStatement());
连接->sql\u连接->设置自动提交(false);
//语句->执行(“启动事务”);
std::unique_ptr rs(语句->executeQuery(“从ww_作业中选择id进行更新,其中状态=0,按id限制1排序进行更新”);
如果(rs->next()){
db_id=rs->getInt64(1);
调试sql_连接->提交();
“释放与池()的连接;”
但这种方法似乎效率不高。我总是回来

错误代码:1205,SQLState:HY000。详细信息:

来自很多线程,特别是当负载增加时


为什么我要收回这些?最有效的方法是什么,硬一致性是一项要求。

根据我的经验,完成这项任务的最佳方法是使用redis队列。 锁定表SELECT…FOR UPDATE在运行多线程应用程序等时挂起数据库

我建议您安装一个redis,并编写一些脚本,根据表中的数据创建队列,并重写您的程序以使用redis队列执行任务。
redis队列不会为不同的线程提供相同的值,因此您可以获得唯一性,并且数据库中没有锁-因此您的脚本可以快速工作。

根据我的经验,执行此任务的最佳方法是使用redis队列。 锁定表SELECT…FOR UPDATE在运行多线程应用程序等时挂起数据库

我建议您安装一个redis,并编写一些脚本,根据表中的数据创建队列,并重写您的程序以使用redis队列执行任务。
redis队列不会为不同的线程提供相同的值,因此您可以获得唯一性,并且数据库中没有锁-因此您的脚本可以快速工作。

您可以缩短事务持续时间吗?我的意思是

您的状态值为0表示“等待”,1表示“完成”。使用状态值2(或-1,或您选择的任何值)表示“正在工作”

然后,当工作线程从表中获取要执行的作业时,它将执行此操作(伪SQL)

完成时

      UPDATE ww_jobs_for_update 
        SET thread = NULL, status = 1
      WHERE thread = threadId;
因为每个线程都有一个唯一的threadId,而且单个SQL UPDATE语句本身就是一个小事务,所以您可以在不使用任何事务或提交的情况下执行此操作


这两种方法都有一个额外的好处,即您可以使用SELECT查询找出哪些作业处于活动状态。这可能允许您处理由于任何原因而从未完成的作业。

能否缩短事务持续时间?我的意思是

您的状态值为0表示“等待”,1表示“完成”。使用状态值2(或-1,或您选择的任何值)表示“正在工作”

然后,当工作线程从表中获取要执行的作业时,它将执行此操作(伪SQL)

完成时

      UPDATE ww_jobs_for_update 
        SET thread = NULL, status = 1
      WHERE thread = threadId;
因为每个线程都有一个唯一的threadId,而且单个SQL UPDATE语句本身就是一个小事务,所以您可以在不使用任何事务或提交的情况下执行此操作


这两种方法都有一个额外的好处,即您可以使用SELECT查询来找出哪些作业处于活动状态。这可能允许您处理由于任何原因而从未完成的作业。

谢谢。我介绍了thread列并执行了以下语句:“更新ww_作业以更新设置线程=xxx,状态=1,其中状态=0,线程按id限制为空顺序1”;和“从ww_作业中选择id以更新线程=xxxx,状态=1”;但是错误再次发生,1205事务超时。我删除了自动提交(false)和->提交()声明中,DB处于AutoPosie=真模式。错误仍然存在,并且经常在同时出现许多连接时,在C++程序中使用多少个并发线程?与MySQL有多少个并发连接?这是违反直觉的,但通常可以通过减少线程和/或CO的数量来增加吞吐量。谢谢。我介绍了thread列并执行了以下语句:“更新ww_作业,更新设置thread=xxx,状态=1,其中状态=0,线程按id限制为空顺序1”;以及“从ww_作业中选择id,更新线程=xxxx,状态=1”“但是错误再次发生,1205事务超时。我删除了自动提交(false)和->提交()声明中,DB处于AutoPosie=真模式。错误仍然存在,并且经常在同时出现许多连接时,在C++程序中使用多少个并发线程?与MySQL有多少个并发连接?这是违反直觉的,但通常可以通过减少线程和/或CO的数量来增加吞吐量。关系。
UPDATE ww_jobs_for_update SET status=1 WHERE id=" << db_id;
      UPDATE ww_jobs_for_update 
        SET thread = threadId, status = 2
      WHERE status = 0 AND threadId IS NULL
      ORDER BY id LIMIT 1;

      SELECT id FROM ww_jobs_for_update WHERE thread = threadId AND status=2
      UPDATE ww_jobs_for_update 
        SET thread = NULL, status = 1
      WHERE thread = threadId;