Insights into Company
← SQL topics

Corporate Salary: 10,000 Employees

A corporate submits ₹75 crore for 10,000 employees. Follow maker/checker approval, individual bank outcomes and an unresolved timeout through reconciliation.

Illustrative production scenario — fictional educational records

1. Business Scenario

A fictional corporation owes 10,000 employees an average ₹75,000: 10,000 × 75,000 = ₹750,000,000 = ₹75 crore. The batch is an operational grouping of independent payment obligations, not a single all-or-nothing bank transaction.

The bank reports 9,970 SUCCESS, 20 FAILED and 10 PENDING/UNKNOWN. This lesson displays status PARTIALLY_COMPLETED with processing_status PROCESSING and is_final = false. The label reports progress, not finality: all ten unresolved items remain visible.

The eventual illustrated outcome is 9,980 successes and 20 confirmed failures. Only then processing_status becomes CLOSED and is_final=true. Bank balance shown in a local cache is not an authority to spend without the bank's balance/reservation controls.

Illustrative values only
ReferenceAmount per main requestScope
SAL-2026-09-EMP005₹75,000External outcome plus local allocation

2. Real Database Tables

These are educational schema definitions, not tables to add to the job portal's live database. PK means primary key; FK means a foreign key to the named parent. Use DECIMAL(19,2) for stored money and integer minor units or decimal-safe arithmetic in application code.

Use MySQL InnoDB for these row-locking examples. NOT NULL, foreign keys and scoped UNIQUE constraints complement application validation. Monetary CHECK constraints require an engine/version that enforces them; the service must still reject invalid amounts.

corporate_accounts

corporate_accounts — educational schema
ColumnType / constraint
idBIGINT PK
company_idBIGINT
bank_account_idBIGINT FK protected bank account
statusVARCHAR(20)
available_balanceDECIMAL(19,2)
balance_as_ofTIMESTAMP

₹80 crore is an illustrative bank-reported snapshot. Bank reservations and fees affect actual available cash.

salary_batches

salary_batches — educational schema
ColumnType / constraint
idBIGINT PK
company_idBIGINT
batch_referenceVARCHAR(100) UNIQUE
salary_monthCHAR(7)
employee_countINT
total_amountDECIMAL(19,2)
statusVARCHAR(30)
processing_statusVARCHAR(20)
is_finalBOOLEAN
created_byBIGINT
approved_byBIGINT NULL
created_atTIMESTAMP
approved_atTIMESTAMP NULL
submitted_atTIMESTAMP NULL

created_by 11 != approved_by 22. A valid permission check is required in addition to different IDs.

salary_batch_items

salary_batch_items — educational schema
ColumnType / constraint
idBIGINT PK
salary_batch_idBIGINT FK
employee_idBIGINT
beneficiary_accountVARCHAR(100) encrypted/tokenized
amountDECIMAL(19,2)
bank_codeVARCHAR(30)
statusVARCHAR(30)
payment_referenceVARCHAR(100) UNIQUE
failure_codeVARCHAR(100) NULL

Beneficiaries and bank codes are deliberately non-routable example tokens. Validate actual identifiers using the bank's supported scheme.

bank_payment_requests

bank_payment_requests — educational schema
ColumnType / constraint
idBIGINT PK
batch_item_idBIGINT UNIQUE FK
business_referenceVARCHAR(100) UNIQUE
amountDECIMAL(19,2)
statusVARCHAR(30)
attempt_countINT
external_referenceVARCHAR(100) NULL

The same business reference remains on every investigation or safe retry.

bank_responses

bank_responses — educational schema
ColumnType / constraint
idBIGINT PK
request_idBIGINT FK
provider_event_idVARCHAR(100) UNIQUE
bank_referenceVARCHAR(100)
statusVARCHAR(30)
amountDECIMAL(19,2)
received_atTIMESTAMP

Append verified responses; prevent duplicate event application. A response is evidence, not permission to double-pay.

reconciliation_records

reconciliation_records — educational schema
ColumnType / constraint
idBIGINT PK
payment_referenceVARCHAR(100)
internal_statusVARCHAR(30)
external_statusVARCHAR(30)
amountDECIMAL(19,2)
statusVARCHAR(30)
resolutionVARCHAR(255) NULL

Resolve only after matching company, beneficiary, amount, currency, date and bank reference.

audit_logs

audit_logs — educational schema
ColumnType / constraint
idBIGINT PK
user_idBIGINT NULL (system actors allowed)
actionVARCHAR(60)
entity_typeVARCHAR(60)
entity_idBIGINT
old_statusVARCHAR(30) NULL
new_statusVARCHAR(30)
metadataJSON redacted
created_atTIMESTAMP

Append-only access policy; timestamps and actor identity explain who changed a result. Avoid full bank details or secrets in metadata.

outbox_events

outbox_events — educational schema
ColumnType / constraint
idBIGINT PK
event_keyVARCHAR(150) UNIQUE
aggregate_referenceVARCHAR(100)
event_typeVARCHAR(60)
payloadJSON
created_atTIMESTAMP
published_atTIMESTAMP NULL

Write in the financial transaction; a dispatcher retries unpublished events. Consumers also deduplicate because queue delivery may repeat.

3. Sample Table Data

The rows below are fictional starting records. NULL means no confirmed value is known. Empty ledger/document tables are intentional before processing; their inserted records appear in Final Database State.

Large-population examples show representative rows, not all 2,000 or 10,000 records. Run totals refer to the complete illustrative population, not the displayed subset.

corporate_accounts — before processing
idcompany_idbank_account_idstatusavailable_balancebalance_as_of
9044900ACTIVE800000000.002026-09-28 08:00:00
salary_batches — before processing
idcompany_idbatch_referencesalary_monthemployee_counttotal_amountstatusprocessing_statusis_finalcreated_byapproved_bycreated_atapproved_atsubmitted_at
5044BATCH-2026-09-442026-0910000750000000.00PARTIALLY_COMPLETEDPROCESSINGfalse11222026-09-28 08:10:002026-09-28 08:30:002026-09-28 09:00:00
salary_batch_items — before processing
idsalary_batch_idemployee_idbeneficiary_accountamountbank_codestatuspayment_referencefailure_code
50001501TOKEN-EMP00175000.00DEMO-BANKSUCCESSSAL-2026-09-EMP001NULL
50002502TOKEN-EMP00275000.00DEMO-BANKSUCCESSSAL-2026-09-EMP002NULL
50003503TOKEN-EMP00375000.00DEMO-BANKFAILEDSAL-2026-09-EMP003ACCOUNT_CLOSED
50004504TOKEN-EMP00475000.00DEMO-BANKFAILEDSAL-2026-09-EMP004INVALID_ACCOUNT
50005505TOKEN-EMP00575000.00DEMO-BANKUNKNOWNSAL-2026-09-EMP005BANK_TIMEOUT
50006506TOKEN-EMP00675000.00DEMO-BANKSUCCESSSAL-2026-09-EMP006NULL
bank_payment_requests — before processing
idbatch_item_idbusiness_referenceamountstatusattempt_countexternal_reference
6000550005SAL-2026-09-EMP00575000.00UNKNOWN1NULL
bank_responses — before processing
idrequest_idprovider_event_idbank_referencestatusamountreceived_at
6100560005EVT-STATUS-005BANK-005SUCCESS75000.002026-09-28 12:00:00
reconciliation_records — before processing
idpayment_referenceinternal_statusexternal_statusamountstatusresolution
62005SAL-2026-09-EMP005UNKNOWNSUCCESS75000.00OPENNULL
outbox_events — before processing
event_keypublished_at
No rows yet — this is the state before processing.

4. User Action / Request

The request is a business intent, not an instruction to trust browser-supplied status, owner or balance. The controller authorizes the actor, validates shape and currency, and resolves the saved obligation.

Button click to recorded result

  1. Corporate payroll freezes amounts
  2. Maker 11 creates batch
  3. Validate 10000 items and sum
  4. Checker 22 approves
  5. Outbox and payment orchestrator
  6. Bank-specific adapter
  7. Independent bank outcomes
  8. Status query for EMP005
  9. Reconciliation
  10. Salary documents
Request envelope (illustrative)
FieldValue / rule
referenceSAL-2026-09-EMP005
amount₹75,000; validate against saved request
authenticated actorBANK-STATUS-RECONCILER
responseReturn saved result on duplicate; show pending while unresolved

5. What Happens Inside the Application

Validate count, sum, positive amounts, employee eligibility, beneficiary scheme and unique payment references before approval. Reject malformed rows without any financial operation. Bind the maker's payload and version to the checker approval so editing a batch invalidates approval.

The orchestrator claims one saved request, records submission intent, commits, and calls the bank adapter. Only the adapter knows the bank's protocol and authentication. No worker may silently invent SAL-2026-09-EMP005-RETRY-2 after a timeout.

The reconciler verifies response EVT-STATUS-005 against the saved ₹75,000 obligation. It locks request 60005 and item 50005 in the standard order, records BANK-005 and SUCCESS once, resolves exception 62005, and creates document/audit outbox work. Derived batch counts still retain the other nine unresolved items until each is confirmed.

Application responsibility boundaries

  1. Request
  2. Controller: authorize / validate
  3. Service: business rules / idempotency
  4. Database: locks / constraints / atomic writes
  5. Adapter: external protocol
  6. Callback / reconciler: verify evidence
  7. Outbox and document worker

6. Database Transaction

Transaction boundaries

  1. Verified bank query returns BANK-005 SUCCESS
  2. BEGIN
  3. Lock request 60005
  4. Lock item 50005
  5. Check matching amount/reference and current state
  6. UNKNOWN → SUCCESS, save bank reference
  7. Resolve reconciliation 62005; audit/outbox
  8. COMMIT
  9. Recompute batch outcome counts

Atomicity applies to the writes enclosed by one BEGIN/COMMIT. Consistency means the amount, status, ledger/allocation and audit invariants agree. Isolation prevents conflicting decisions on locked rows. Durability means a committed result survives a client disconnect.

On unexpected database errors, roll back the local transaction. A known business rejection can instead be recorded and committed without a financial mutation. Never swallow a database exception and accidentally commit half of the intended changes.

Do not hold an invoice/account/item lock across bank network calls. Persist the intent first, commit it, then call the adapter. Apply verified results in a new short transaction. A database rollback cannot recall money already moved by an external bank.

7. SQL Query

SQL fragments show the successful branch of an application-controlled transaction. Comments describing checks are real control-flow requirements: the handler must stop/rollback or record the specified exception when a guard fails. Do not paste all branches as one unconditional money-moving script.

Representative SQL and guarded updates

START TRANSACTION;
SELECT * FROM bank_payment_requests WHERE id = 60005 FOR UPDATE;
SELECT id, amount, payment_reference, status FROM salary_batch_items WHERE id = 50005 FOR UPDATE;
-- Apply only a verified matching bank result; an existing SUCCESS is a no-op.
UPDATE bank_payment_requests SET status = 'SUCCESS', external_reference = 'BANK-005' WHERE id = 60005;
UPDATE salary_batch_items SET status = 'SUCCESS', failure_code = NULL WHERE id = 50005;
UPDATE reconciliation_records SET status = 'RESOLVED', resolution = 'Verified BANK-005; no resubmission' WHERE id = 62005;
-- Audit/outbox entry records UNKNOWN -> SUCCESS.
COMMIT;
SELECT status, COUNT(*) AS items, SUM(amount) AS total
FROM salary_batch_items WHERE salary_batch_id = 50 GROUP BY status;
-- Close the parent only when PENDING/UNKNOWN/READY/SUBMITTED/PROCESSING count is zero.

Use prepared parameters in application code; literal IDs are used here only so learners can track the sample rows. Verify affected-row counts before the next financial write. Unique-reference violations require inspection of the existing saved outcome, not a new debit.

8. Concurrent Request Scenario

Concurrent request timeline
TimeRequest / worker ARequest / worker B or external system
T0Worker sends EMP005 using saved referenceBank accepts request
T1HTTP response times out; record UNKNOWNBank may already have paid
T2Retry worker claims investigation, not paymentQuery original reference
T3Query returns BANK-005 SUCCESS; lock requestConcurrent callback waits on same request
T4Commit SUCCESS once; resolve exceptionDuplicate result becomes a no-op

A waiting worker must re-read the row after it obtains the lock. A value read before waiting cannot authorize a later debit/allocation. A second delivery of one business request differs from a genuinely new request: the former returns the same outcome, while the latter must recheck current funds or remaining obligation.

9. Locking / Isolation

SELECT ... FOR UPDATE is a locking read inside an explicit InnoDB transaction. The row remains protected until COMMIT or ROLLBACK. Use indexed primary/unique lookups so the operation does not scan and lock unrelated data.

Every handler touching multiple entities must follow the same lock hierarchy. Define it once for workers, callbacks and reconcilers; opposite order can create deadlocks. A deadlock victim must restart the whole local transaction and re-read data.

Lock the saved business request/payment first, then its mutable account/invoice/item. Keep the transaction short and use current locked values, even if an earlier page showed a different balance.

Lock lifetime

  1. BEGIN
  2. Indexed locking read
  3. Validate current row
  4. Guarded mutation
  5. COMMIT / ROLLBACK
  6. Lock released

10. Calculation

Calculation and invariants
ValueCalculation / expected result
Batch total10000 × 75000 = 750000000 (₹75 crore)
Initial successes9970 × 75000 = 747750000
Confirmed failures20 × 75000 = 1500000
Unresolved amount10 × 75000 = 750000
Final successes9980 × 75000 = 748500000
Final unpaid failures1500000; not rolled back successful cash

Amounts shown in tables use two decimal places; commas and ₹ are display formatting, not database values. Round according to the documented currency/payroll rule once at the defined boundary. Do not add salary strings using floating-point arithmetic or silently change approved historical totals.

11. Table Update — Before / After

Before / request / after
Table or fieldBeforeAfter
EMP005UNKNOWN / BANK_TIMEOUTSUCCESS / BANK-005
request 60005 attempts11 (status inquiry is not a second payment)
reconciliation 62005OPENRESOLVED
batch 50 pending/unknown count109 after EMP005; 0 after all ten resolutions
batch 50 is_finalfalsetrue only after zero unresolved items

The after rows describe only committed outcomes. A rollback preserves the before financial rows; a separately committed failure/audit record can still describe the rejected request. Background document status changes do not rewrite the financial success.

12. Status Transition

Success branch

  1. INITIATED / READY
  2. SUBMITTED
  3. PENDING / PROCESSING
  4. Verified SUCCESS

Failure / investigation branch

  1. SUBMITTED
  2. Timeout → UNKNOWN
  3. Query / callback / reconcile
  4. Verified SUCCESS or confirmed FAILED

Refund branch

  1. SUCCESS
  2. Authorized REFUND_REQUESTED
  3. Provider confirmation
  4. REFUNDED; retain original payment
Meaning of each state
StateMeaning
READY / INITIATEDSaved intent; not proof of bank receipt
SUBMITTEDSend attempted; bank outcome not yet final
PENDING / PROCESSINGProvider confirms work in progress
UNKNOWNNo reliable external final outcome yet
SUCCESSVerified final external success applied once locally
FAILEDConfirmed rejection; no blind assumption on timeout
REFUND_REQUESTED / REFUNDEDSeparate authorized refund workflow with its own result

Batch summary PARTIALLY_COMPLETED is deliberately non-final while processing_status=PROCESSING and is_final=false. Success, failed and unresolved counters remain visible. Close only after all unresolved items reach an evidenced final result.

Corporate parent batch lifecycle

  1. DRAFT: editable
  2. VALIDATED: counts and amounts checked
  3. APPROVED: separate checker authorizes frozen version
  4. SUBMITTED: no assumed success
  5. PROCESSING: unresolved items remain
  6. COMPLETED: all success / PARTIALLY_COMPLETED: inspect finality and counts

13. Success Flow

Success means the defined financial operation and its associated local records are committed. Return the persisted reference and outcome to the client; do not generate a new success on each retry.

Record verified provider/bank evidence before releasing a success notification. A merely submitted request stays pending or unknown until evidence resolves it.

Committed success to user

  1. Saved financial result
  2. COMMIT
  3. Outbox dispatcher
  4. Idempotent document job
  5. Private document ready
  6. Notification / authorized download

14. Failure Flow

ACCOUNT_CLOSED, INVALID_ACCOUNT and BENEFICIARY_BLOCKED are confirmed failures only when the bank reports a terminal rejection. BANK_TIMEOUT is UNKNOWN. PENDING means the bank says processing; UNKNOWN means the application does not know. Record each item result and keep unresolved amounts visible.

Failure classification
FailureLocal actionFinancial interpretation
Negative amount / invalid payloadREJECTED before submissionNo financial operation
Insufficient funds / inactive entityRecord confirmed business failureNo local debit
Database error before external sendROLLBACKRetry only the rolled-back operation
Verified ACCOUNT_CLOSEDFAILEDConfirmed external rejection
BANK_TIMEOUT / lost responseUNKNOWN; investigateMay already have succeeded
PDF / email errorRetry document/notification onlyPayment remains SUCCESS

15. Retry Flow

Do not create SAL-2026-09-EMP005-RETRY-2 merely to get a new request accepted. Query the original reference, await signed callback or compare the bank statement. Retry transmission only when the adapter/provider contract establishes it is safe; preserve the original business key and record each attempt separately.

Safe retry decision

  1. Find original saved reference
  2. Was any external request sent?
  3. Yes / uncertain → query original provider reference
  4. Confirmed success → return; never repeat effect
  5. Confirmed safe failure → bounded authorized retry
  6. Exhausted / unresolved → investigation queue

Use bounded exponential backoff for transient technical errors and expose retry age/attempt count. An exhausted job becomes a failed/dead-letter item for an operator; a queue retry counter is not evidence of bank failure. A corrected obligation or authorized refund is a distinct linked business operation, not a stealth retry.

16. Idempotency

Repeated deliveries
DeliveryBusiness referenceExpected financial effect
FirstSAL-2026-09-EMP005Apply once after validation/confirmation
SecondSAL-2026-09-EMP005Return existing result / wait for original
ThirdSAL-2026-09-EMP005No additional debit, allocation or salary

Persist a unique business key before processing and compare the request payload on key reuse. Apply another unique constraint to the external event/reference and to the document/outbox event. A unique key alone is not enough: the status check and financial mutation must be within the same transaction.

Callback authentication and idempotency solve different problems. Verify signatures/merchant context first; an attacker-controlled reference does not become trusted just because it is unique. Lock the request row before applying its result.

17. Queue / Background Processing

Durable background work

  1. Financial transaction inserts outbox event
  2. COMMIT
  3. Dispatcher reads unpublished events
  4. Queue accepts event
  5. Idempotent worker executes
  6. Mark completed / retry with same event key
outbox_events — after financial commit
event_keyaggregate_referenceevent_typepublished_at
SAL-2026-09-EMP005:documentSAL-2026-09-EMP005GENERATE_DOCUMENTNULL until dispatched

Laravel afterCommit() prevents a worker from reading an uncommitted row, but a process can still crash between database commit and sending to a separate queue. A transactional outbox closes that publication gap; consumers must still handle redelivery.

Separate payment, document, notification and reconciliation queues allow independent retries and limits. Payroll/corporate schedulers paginate or chunk work rather than loading all 10,000 payments into one transaction. Do not submit external payments again just because their notification jobs failed.

Laravel dispatch after commit (illustrative job class)

GenerateSalaryAdvice::dispatch($batchItem->id)->afterCommit();
// Job class is illustrative. Use a durable outbox for reliable publication.
// Deduplicate by the saved payment/request/document identity.

18. Receipt / Document Generation

Salary advice for EMP005 includes batch BATCH-2026-09-44, ₹75,000, business reference SAL-2026-09-EMP005 and bank reference BANK-005. Generate after confirmation and commit; restrict download to the employee or authorized payroll staff.

Sample private document — fictional educational values
Document fieldStored value
Salary adviceADVICE-2026-09-EMP005
BatchBATCH-2026-09-44
EmployeeEMP005
ReferenceSAL-2026-09-EMP005
Bank referenceBANK-005
Amount paidINR 75000.00
StatusSUCCESS after reconciliation

Private document lifecycle

  1. Confirmed SUCCESS
  2. Database COMMIT
  3. Pending document / outbox
  4. Queue PDF renderer
  5. Private storage
  6. GENERATED
  7. Authorized download
Document failure is independent
PaymentDocumentAction
SUCCESSPENDINGWait for document worker
SUCCESSFAILED_GENERATIONRetry renderer with same document key
SUCCESSGENERATEDReuse existing file; authorize each download

Render from the committed immutable amount/reference and approved payroll snapshot, not client input. Reserve a unique receipt/slip number and link one document to one payment. A failed write to private storage cannot turn the already-confirmed financial payment into FAILED.

19. Reconciliation

Join internal items and the bank report by business reference and bank reference, then verify beneficiary token, amount, currency and date. Initial successes 9970 differ from bank-confirmed 9980; the ten missing confirmations are resolved individually. Compare cash totals with settlement/fees, not just counts. Twenty confirmed failures remain liabilities to investigate.

Three-way evidence check

  1. Internal request / ledger / allocation
  2. Compare provider confirmation by reference
  3. Compare bank settlement by date/currency/net policy
  4. Create discrepancy record
  5. Investigate with evidence
  6. Apply idempotent authorized correction
  7. Close exception with audit
Illustrative reconciliation record
referenceinternal beforeevidencestatus / resolution
SAL-2026-09-EMP005UNKNOWN / missing confirmationVerified provider/bank successResolved only after matching identity and amount

Investigate outcomes, never blindly overwrite

-- Grouping is a monitoring signal; investigate individual references.
SELECT status, COUNT(*) AS rows_found, SUM(amount) AS amount_total
FROM salary_batch_items
GROUP BY status;

Count mismatches are clues, not sufficient proof. Match identifiers, amounts, currency, beneficiary and dates. Handle settlement lag, fees and refunds explicitly; never change thousands of rows to SUCCESS merely to make dashboard totals agree.

20. Audit Log

Actual illustrative audit records
actoractionentityold_statusnew_statuscreated_at
BANK-STATUS-RECONCILERREQUEST_SAVEDSAL-2026-09-EMP005NULLUNKNOWN2026-09-28 09:00:00
VERIFIED-CALLBACKRESULT_APPLIEDSAL-2026-09-EMP005UNKNOWNSUCCESS2026-09-28 12:00:00
DOCUMENT-WORKERDOCUMENT_GENERATEDSAL-2026-09-EMP005PENDINGGENERATED2026-09-28 12:01:00

Each financial status change appends an audit event inside the same local transaction. Metadata includes the request ID, correlation ID, provider evidence reference and reason, with secrets and full beneficiary details removed.

Restrict update/delete permissions on audit history and define retention. A manual reconciliation resolution records the authorized operator, evidence and correction reference. Audit explains who changed a value; the ledger explains the financial entries.

21. Final Database State

These tables describe the completed illustrative main scenario. Independent failure/overpayment exercises above do not silently alter these rows. Batch counts below are derived reporting values where marked.

salary_batches (derived totals) — final
idsuccessfailedunresolvedstatusprocessing_statusis_final
509980200PARTIALLY_COMPLETEDCLOSEDtrue
salary_batch_items — final
employeeamountstatusreference
EMP00575000.00SUCCESSSAL-2026-09-EMP005
EMP00375000.00FAILEDSAL-2026-09-EMP003
reconciliation_records — final
idstatusresolution
62005RESOLVEDBANK-005 confirmed; no duplicate submission
Document/outbox final checkpoint
Financial resultDocumentOutbox
SUCCESSGENERATED after independent jobPublished; worker deduplicates redelivery

22. Interview Questions

Can PARTIALLY_COMPLETED hide ten pending items?

No. In this explicit model the summary coexists with PROCESSING and is_final=false until every item is resolved.

What does the checker approve?

The frozen company/month/count/amount/beneficiary payload version, after independent authorization; not an editable batch that the maker can later change.

Why SELECT FOR UPDATE?

Protect a mutable row while the transaction makes and applies a decision from its current value.

What does a waiting request read?

The new committed value after obtaining its lock, not a cached value from before waiting.

Why cannot local rollback reverse a bank payment?

The bank is outside the local transaction boundary; use verified reconciliation and a separate authorized reversal/refund.

How are duplicate webhooks prevented from repeating money effects?

Authenticate the event, persist unique provider/business keys, lock the saved payment and apply the final result once.

What distinguishes FAILED, PENDING and UNKNOWN?

Confirmed rejection; confirmed work in progress; and unresolved external outcome, respectively.

How do 5,000 student payments or 10,000 salaries scale?

Persist independent obligations, use controlled idempotent workers, avoid long global locks, and reconcile each result.

Why queue receipt generation?

Document availability can retry independently without changing a confirmed financial outcome.

What should a deadlock retry repeat?

The entire rolled-back local transaction with its original business identity; never an uncertain external payment.

23. Related SQL Concepts

Connect the sample to ACID, row locks, isolation levels, foreign keys, UNIQUE constraints, conditional UPDATE, SUM/GROUP BY, joins, NULL external references and state transitions. Use window functions to review ordered attempts while preserving each payment's business identity.

MySQL locking reads · Laravel queues and transactions