バッチ処理で大量の電子メールを送信しています。このプロセスはCFThreadの内部で実行されます。各レコードセットはSQL Serverから取得されます。電子メールをループすると、送信されたレコードが更新されます。CFThreadバッチ処理 - 複数回処理されているレコード
毎分プロセスを実行すると、正常に動作します。 30秒ごとに実行すると、レコードの処理が複数回開始されます。
レコードを「引っ張った」とフラグを立てても、まだ問題が残っていました。 第1の要求がまだ処理中であるように見えます。第2の要求が開始されます。第2の要求は、第1の要求がそれらを「引っ張られた」とフラグ付けする前にレコードを検索する。したがって、同じレコードが2回処理されます。
テーブルをロックしたくないのは、私がレコードを引っ張っている間に、同じテーブルに送信されたように電子メールを送信し、他のレコードを更新しているからです。
データベース:(擬似コード)
BEGIN
DECLARE @MyTempTable table(
ID INT IDENTITY(1,1) NOT NULL,
emailBody varchar(max),
eMailfromdisplay varchar(200),
eMailFromAdr varchar(200),
eMailsubject varchar(200),
emailAdr varchar(200),
FirstName_vch varchar(250),
LastName_vch varchar(250),
Sent INT,
pulled INT,
masterEmailTableID BIGINT
);
insert into @MyTempTable
select Distinct top 1000
emailBody,
eMailfromdisplay,
eMailFromAdr,
eMailsubject,
emailAdr,
FirstName,
LastName,
Sent,
pulled ,
masterEmailTableID
from
emailMasteTable
where
pulled = 0 and
Sent = 0
SELECT TOP 1000 id
,masterEmailTableID
,Email_adr
,firstName
,LastName
,Sent
,pulled
FROM @MyTempTable where sent = 0 and pulled = 0
-- Other tables status updates
update emailMasteTable set pulled = 1 where EmailID IN (Select distinct masterEmailTableID from @MyTempTable);
END
のColdFusion:(擬似コード)
<cfquery name="getMessages">
exec spGetEmailMessages
</cfquery>
<cfoutput query="getMessages">
<cfmail>
<!--- Email Stuff --->
<cfquery>
update emailMasteTable set sent = 1 where EmailID = #getMessages.masterEmailTableID#;
</cfquery>
</cfmail>
</cfoutput>
実際のスクリプトを見ずに言うことはできないと思いますが、可能なら共有してください。 – Susang
複数のスレッドがレコードにアクセスする可能性がある場合は、それらが処理された後に完了*としてフラグを付けるだけでは不十分です。競合状態を防ぐために、ある種のロック機構を実装しなければならない(MUST)。たとえば、新規、処理中、完了済み、失敗した複数のステータスを実装できます。ステータスがnewのレコードをチェックし、検索時に*フラグを付けます。これにより、他のプロセスが同じデータを取得するのを防ぐことができます。処理が完了したら、通常どおり完了/失敗としてマークします。 – Leigh
*引っ張ったときにレコードにフラグを立てても、引き続き問題に直面しますが、正しく実行すれば起こりません。いくつかのコードを投稿する必要があります。具体的には、そのロジックの一部です。 – Leigh