0

準備されたステートメントでコマンドを使用MERGEしましたが、シングルスレッド環境で実行すると正常に動作しますが、マルチスレッド環境では問題が発生します。つまり、データが複製されます。つまり、5 つのスレッドがある場合、各レコードは 5 回複製されます。スレッドを支援するためのロックが db にないと思います。私のコード:

//db:oracle
sb.append("MERGE INTO EMP_BONUS EB USING (SELECT 1 FROM DUAL) on (EB.EMP_id = ?) WHEN MATCHED  THEN  UPDATE SET TA =?,DA=?,TOTAL=?,MOTH=?  WHEN NOT MATCHED THEN "+ "INSERT (EMP_ID, TA, DA, TOTAL, MOTH, NAME)VALUES(?,?,?,?,?,?) ");

//sql operation,calling from run() method
public void executeMerge(String threadName) throws Exception {              
        ConnectionPro cPro = new ConnectionPro();
        Connection connE = cPro.getConection();
        connE.setAutoCommit(false);
        System.out.println(sb.toString());
        System.out.println("Threadname="+threadName);
        PreparedStatement   pStmt= connE.prepareStatement(sb.toString());
        try {
            count = count + 1;

            for (Employee employeeObj : employee) {//datalist of employee

                pStmt.setInt(1, employeeObj.getEmp_id());
                pStmt.setDouble(2, employeeObj.getSalary() * .10);
                pStmt.setDouble(3, employeeObj.getSalary() * .05);
                pStmt.setDouble(4, employeeObj.getSalary()
                        + (employeeObj.getSalary() * .05)
                        + (employeeObj.getSalary() * .10));
                pStmt.setInt(5, count);
                pStmt.setDouble(6, employeeObj.getEmp_id());
                pStmt.setDouble(7, employeeObj.getSalary() * .10);
                pStmt.setDouble(8, employeeObj.getSalary() * .05);
                pStmt.setDouble(9, employeeObj.getSalary()
                        + (employeeObj.getSalary() * .05)
                        + (employeeObj.getSalary() * .10));
                pStmt.setInt(10, count);
                pStmt.setString(11, threadName);
                // pStmt.executeUpdate();

                pStmt.addBatch();
            }

            pStmt.executeBatch();
            connE.commit();
        } catch (Exception e) {
            connE.rollback();
            throw e;

        } finally {

            pStmt.close();
            connE.close();

        }
    }

employee.size=5、thread count =5 の場合、実行後、5 ではなく 25 レコードを取得します。

4

1 に答える 1

0

制約がない場合 (例: のemp_id列に対する主キー制約または一意キー制約emp_bonus)、データベースが各スレッドに 5 行の挿入を許可することを妨げるものは何もありません。各データベース セッションは、他のセッションによって行われたコミットされていない変更を見ることができないため、各スレッドは、スレッドが探している行が存在しないことを認識します (同じ 5 を返すと仮定していemp_bonusます)。emp_idemployeeObj.getEmp_id()emp_id各スレッドの値) したがって、5 つのスレッドがある場合、各スレッドは 5 行すべてを挿入し、合計 25 行になります。重複する行が挿入されないようにする一意の制約がある場合、Oracle は、最初のスレッドがコミットするまで他の 4 つのスレッドをブロックすることを許可し、後続のスレッドが挿入ではなく更新を実行できるようにします。もちろん、これによりスレッドがシリアル化され、複数のスレッドを実行することで得られるパフォーマンスの向上が無効になります。

于 2012-10-24T12:02:22.023 に答える