1

<EDIT>

この問題は、GET を介して配列を渡し、一部の AJAX コードで URL の長さ制限に達したことに関連していました。POSTメソッドに切り替えることで問題を解決しました。

</EDIT>

SugarCRM データベースで見込み客をバッチ再割り当てするために仕事で使用しているクラスがあります。

この 1 つの関数を除いて、すべてがクラスで完全に機能します。

function reassign($leads = null, $newAssigned = null, $oldAssigned = null)
{
    // How many professionals to assign to?
    $roundrobin = count($newAssigned) - 1;
    $recurse = 0;

    if (!isset($leads)) {
        die("You must select the accounts to reassign!");
    }
    if (!isset($newAssigned)) {
        die("You must select a Professional!");
    }
    if (!isset($oldAssigned)) {
        die("Something broke in the Assigning process. Check javascript.");
    }

    try {
    foreach ($leads as $key => $value) {
        $sql_update = "UPDATE accounts SET assigned_user_id = '".$newAssigned[$recurse]."' WHERE id = '".$value."'";
        $assignment = $this->db_handle->prepare($sql_update);
        $assignment->execute();
        unset($assignment);

        $sql_statement = "INSERT INTO accounts_audit 
                            (id,
                            parent_id,
                            date_created,
                            created_by,
                            field_name,
                            data_type,
                            before_value_string,
                            after_value_string)
                        VALUES (uuid(),
                                '".$value."',
                                now(),
                                '".$_SESSION['session_user_id']."',
                                'assigned_user_id',
                                'relate',
                                '".$oldAssigned[$key]."',
                                '".$newAssigned[$recurse]."')";

        $audit_statement = $this->db_handle->prepare($sql_statement);
        $audit_statement->execute();
        unset($audit_statement);

        if ($recurse < $roundrobin) {
            $recurse++;
        } else {
            $recurse = 0;
        }
    }
    catch (Exception $e) {
        echo 'Caught exception: ',  $e->getMessage(), "\n";
    }
    echo "Successful!\n";
}

この機能により、ユーザーは生成されたリストから任意の数のリードをチェックし、それらのリードをリスト内の任意の数の担当者に均等に再割り当てし、それらの変更を監査目的でテーブルに記録できます。

私が抱えている問題は、ユーザーが 20 ~ 25 程度のリードを選択すると、この機能が停止してハングすることです。20 未満の場合、ハングすることはありません。ユーザーは何百、場合によっては何千ものリードを再割り当てできる必要があるため、これは問題です。

このようにロックする理由 (ロックするリードの数はさまざまで、通常は 20 ~ 25) について何か考えはありますか? リード数が 20 を下回ると、すぐに変更されます。

編集:

ステートメントのクローズを表示するようにコードを更新しました。相変わらず行動に変化なし。破損の原因となるリードの数が選択されている場合、変更は行われません。最初の 19 ~ 20 は実行せず、残りで停止します。変更は行われず、監査テーブルには何も追加されません。限界点未満で、すべての変更が行われ、監査テーブルに記録されます。

私はPDOを使用してdbに接続しています:

try {
    $this->db_handle = new PDO("mysql:host=$this->dbHost;dbname=$this->dbDatabase", $this->dbUsername, $this->dbPassword);
    $this->db_handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}

そして、そこにエラーはありません。また、どのコードのログにもエラーはありません。私はとても混乱しています。

編集#2:

提案によると、バインドされたパラメーターと同じです...

function reassign($leads = null, $newAssigned = null, $oldAssigned = null)
{
    // How many professionals to assign to?
    $roundrobin = count($newAssigned) - 1;
    $recurse = 0;

    $sql_assign = "UPDATE accounts SET assigned_user_id = :new_user_id WHERE id = :account_id";
    $sql_audit  = "INSERT INTO accounts_audit
                            (id,
                            parent_id,
                            date_created,
                            created_by,
                            field_name,
                            data_type,
                            before_value_string,
                            after_value_string)
                        VALUES (uuid(),
                                :parent_id,
                                now(),
                                :created_by,
                                'assigned_user_id',
                                'relate',
                                :old_assigned_user,
                                :new_assigned_user)";

    $assignment = $this->db_handle->prepare($sql_assign);
    $audit      = $this->db_handle->prepare($sql_audit);

    if (!isset($leads)) {
        die("You must select the accounts to reassign!");
    }
    if (!isset($newAssigned)) {
        die("You must select a Professional!");
    }
    if (!isset($oldAssigned)) {
        die("Something broke in the Assigning process. Check javascript.");
    }

    try {
    foreach ($leads as $key => $value) {
        $assign_params = array(':new_user_id' => $newAssigned[$recurse], ':account_id' => $value);
        $assignment->execute($assign_params);

        $audit_params = array(':parent_id' => $value, ':created_by' => $_SESSION['session_user_id'], ':old_assigned_user' => $oldAssigned[$key], ':new_assigned_user' => $newAssigned[$recurse]);
        $audit->execute($audit_params);

        if ($recurse < $roundrobin) {
            $recurse++;
        } else {
            $recurse = 0;
        }
    }
    catch (Exception $e) {
        echo 'Caught exception: ',  $e->getMessage(), "\n";
    }
    echo "Successful!\n";
}

それが機能する場合に高速になることを除いて、違いはありません。:(

4

2 に答える 2

1

私の推測では、あなたは準備されたステートメントを漏らしていると思います。エラーログに手がかりがある可能性があります。

プリペアドステートメントを使用しているので、ループの外側でそれらを準備し、ループの内側のパラメーターでそれらを実行してみませんか?ここではmysqliを使用していると想定しています。その場合は、bind_paramを使用する必要があります。

そうすれば、すべてのプリペアドステートメントを作成するだけです!

//example prepare
$assignUser= $this->db_handle->prepare(
    "UPDATE accounts ".
    "SET assigned_user_id=? ".
    "WHERE id=?");


while (...)
{
    //example bind + execute
    $assignUser->bind_param("ii", $newAssigned[$recurse], $value);
    $assignUser->execute();


}
于 2012-09-25T15:37:56.580 に答える
0

私が経験していた問題の根本的な原因は、準備されたステートメントの漏洩によるものではありませんでしたが、ポール・ディクソンはそれを防ぐための優れたアドバイスを提供しました.

このスクリプトは、GET メソッドを使用して AJAX 経由で呼び出されました。param1 と param2 の配列が特定の長さに達すると、スクリプトが壊れました。これは、PHP スクリプト自体が原因ではなく、URL が最大長の制限を超えていたために発生していました。

AJAX の GET メソッドから PST メソッドに切り替えると、発生していた問題はすぐになくなりました。

于 2012-10-15T16:10:47.123 に答える