简体   繁体   中英

How to prevent concurrent INSERT in Oracle

During race condition, How to validate number of rows inserted to table A based on permitted row count defined in table B.

#Table A
CAMPAIGN_ID     ISSUE_LIMIT_PER_USER
-----------     --------------------
1000000111      1

#Table B
OFFER_ID    USER_ID     CAMPAIGN_ID   START_DATE  END_DATE
--------    -------     -----------   ----------  --------
11111111    90000       1000000111    2021-06-27  2021-07-27   Request1 allowed 
22222222    90000       1000000111    2021-06-28  2021-07-28   Request2 disallowed
33333333    90000       1000000111    2021-06-29  2021-07-29   Request3 disallowed

NOTE: There is no UNIQUE constraint in table B. Because we can have multiple rows based on the value of ISSUE_LIMIT_PER_USER.

Requirement here is, how to prevent inserting more than 1 record (because ISSUE_LIMIT_PER_USER = 1) into table B when multiple parallel requests are made.

Below SQL I tried but not working.

INSERT INTO B(,,,,) SELECT (,,,,) FROM DUAL WHERE (SELECT COUNT(OFFER_ID) FROM B WHERE 
CAMPAIGN_ID=:campaign_id < :issue_limit_per_user

Because it is an INSERT query it can not lock anything and all parallel threads getting same count and finally inserting 1 row each. This solution works perfectly for other UPDATE use case.

My recommendation is the following.

  1. Create a new table with one row per campaign and per user.
  2. Populate this table with the "used" limit from A .
  3. Also have a column which is the number of "used" rows. Default the value to 0 .
  4. Add a check constraint used_issues <= issue_limit .
  5. Create a trigger on B to keep the value up-to-date for insert s, delete s, and update s.

Voila! The limit will be verified by the check constraint.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM