5

DB で何百万もの行を更新するという問題があるため、それぞれを個別に更新するのではなく、約 1000 ステートメントのグループを単一のクエリに結合したいと考えています。

私はそのようにMULTI_STATEMENTSを有効にしました

client = Mysql2::Client.new(:host => 'localhost', :database => 'mehdb', :username => "root", :password => "", :flags => Mysql2::Client::MULTI_STATEMENTS)

これが私が実行しているコードの例です

sql = "SELECT id, x FROM pew WHERE x IS NULL LIMIT 1000"

results = db_read.query(sql)

while results.count > 0

  updates = ''

  results.each do |r|
    updates += "UPDATE pew SET x = 10 WHERE id = #{r['id']};"
  end

  db_write.query(updates) unless updates.empty?

  results = db_read.query(sql)
end

この作業は、最初の実行中は問題ありませんが、2 番目の一連の更新を起動すると、このエラー メッセージが表示されます。

`query': Commands out of sync; you can't run this command now (Mysql2::Error)

誰もこれに遭遇したことがありますか?または、別のアプローチに関するアドバイスはありますか?

4

4 に答える 4

7

この問題に対する簡単な答えは、MULTI_STATEMENTS が有効になっている場合、mysql はクエリの結果を処理することを期待しています。

簡単な修正は、複数の update ステートメントの各セットの後に、これと同様のことを行うことです

  while db_write.next_result
    db_write.store_result rescue ''
  end
于 2012-06-28T14:26:40.677 に答える
1

私が理解しているように、これはMysqlの内部保護の結果です-DBにクエリを実行し、結果をストリーミングしている最中です。その間に結果も更新する場合、一貫性のレベルを保証できません。

フローの一部として安全に変更できることがわかっている場合は、2 つ目の接続を作成するだけで問題を回避できます。

reading_client = Mysql2::Client.new(:host => 'localhost', :database => 'mehdb', :username => "root", :password => "", :flags => Mysql2::Client::MULTI_STATEMENTS)

updating_client = Mysql2::Client.new(:host => 'localhost', :database => 'mehdb', :username => "root", :password => "", :flags => Mysql2::Client::MULTI_STATEMENTS)


sql = "SELECT id, x FROM pew WHERE x IS NULL LIMIT 1000"

results = reading_client.query(sql)

while results.count > 0

  updates = ''

  results.each do |r|
    updates += "UPDATE pew SET x = 10 WHERE id = #{r['id']};"
  end

  updating_client.query(updates) unless updates.empty?

  results = reading_client.query(sql)
end
于 2014-12-16T06:49:49.633 に答える
1

なぜあなたはちょうど::

何度も実行する必要はありません....

UPDATE pew SET x = 10 WHERE x IS NULL
于 2012-06-26T09:23:18.540 に答える