ਤੁਸੀਂ ਆਰਡਰ ਤਾਂ ਸੇਵ ਕਰ ਲਿਆ, ਪਰ ਆਰਡਰ ਦੀਆਂ ਆਈਟਮਾਂ ਡਾਟਾਬੇਸ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚ ਸਕੀਆਂ। ਜਾਂ ਸ਼ਾਇਦ ਸਟਾਕ ਕਾਊਂਟਰ ਘਟ ਗਿਆ, ਪੇਮੈਂਟ ਗੇਟਵੇਅ ਨੇ ਟਾਈਮਆਊਟ ਦਿੱਤਾ, ਅਤੇ ਹੁਣ ਗਾਹਕ ਦੇ ਕਾਰਡ ਤੋਂ ਪੈਸੇ ਕੱਟੇ ਗਏ ਹਨ ਪਰ ਆਰਡਰ ਦਾ ਕੋਈ ਰਿਕਾਰਡ ਨਹੀਂ ਹੈ। ਇਹ ਸਥਿਤੀਆਂ ਅਜਿਹੀਆਂ ਲੱਗਦੀਆਂ ਹਨ ਜਿਵੇਂ ਕਿ ਇਹ ਕੋਈ ਖਾਸ ਮਾਮਲੇ (edge cases) ਹੋਣ, ਪਰ ਅਜਿਹਾ ਨਹੀਂ ਹੈ। ਇੱਕ ਰੁਝੇਵੇਂ ਵਾਲੇ ਐਪਲੀਕੇਸ਼ਨ ਵਿੱਚ, ਇਹ ਰੋਜ਼ਾਨਾ ਦੀਆਂ ਮੁਸ਼ਕਲਾਂ ਬਣ ਜਾਂਦੀਆਂ ਹਨ।
ਇਸਦਾ ਮੁੱਖ ਕਾਰਨ ਲਗਭਗ ਹਮੇਸ਼ਾ ਇੱਕੋ ਹੀ ਹੁੰਦਾ ਹੈ: ਡਾਟਾਬੇਸ ਲਿਖਣ (writes) ਦੀ ਇੱਕ ਲੜੀ ਜਿਸਨੂੰ ਵੱਖਰੇ, ਅਲਗ-ਅਲਗ ਘਟਨਾਵਾਂ ਵਜੋਂ ਮੰਨਿਆ ਗਿਆ ਸੀ। ਜਦੋਂ ਇੱਕ ਫੇਲ੍ਹ ਹੁੰਦੀ ਹੈ, ਤਾਂ ਬਾਕੀ ਪਿੱਛੇ ਰਹਿ ਜਾਂਦੀਆਂ ਹਨ। ਇਸਦਾ ਹੱਲ ਡਾਟਾਬੇਸ ਟ੍ਰਾਂਜੈਕਸ਼ਨ (database transaction) ਹੈ, ਅਤੇ Laravel ਵਿੱਚ, ਇਸਦਾ ਸਾਧਨ DB::transaction() ਹੈ।
ਇੱਕ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਅਸਲ ਵਿੱਚ ਕੀ ਵਾਅਦਾ ਕਰਦੀ ਹੈ
ਇੱਕ ਡਾਟਾਬੇਸ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਕਈ ਕਾਰਜਾਂ (operations) ਨੂੰ ਕੰਮ ਦੀ ਇੱਕ ਸਿੰਗਲ ਇਕਾਈ (single unit of work) ਵਿੱਚ ਬੰਨ੍ਹ ਦਿੰਦੀ ਹੈ। ਡਾਟਾਬੇਸ ਇੰਜਣ ਇਹ ਗਾਰੰਟੀ ਦਿੰਦਾ ਹੈ ਕਿ ਅੰਦਰਲੀ ਹਰ ਚੀਜ਼ ਜਾਂ ਤਾਂ ਪੱਕੇ ਤੌਰ 'ਤੇ ਕਮਿਟ (commit) ਹੋਵੇਗੀ ਜਾਂ ਪੂਰੀ ਤਰ੍ਹਾਂ ਰੋਲਬੈਕ (rollback) ਹੋ ਜਾਵੇਗੀ। ਇਸ ਵਿੱਚ ਕੋਈ ਵਿਚਕਾਰਲਾ ਰਸਤਾ ਨਹੀਂ ਹੈ।
ਇੱਕ ਬੈਂਕ ਟ੍ਰਾਂਸਫਰ ਬਾਰੇ ਸੋਚੋ। ਸਿਸਟਮ ਨੂੰ ਇੱਕ ਖਾਤੇ ਵਿੱਚੋਂ ਪੈਸੇ ਕੱਟਣੇ ਚਾਹੀਦੇ ਹਨ ਅਤੇ ਦੂਜੇ ਵਿੱਚ ਜਮ੍ਹਾਂ ਕਰਨੇ ਚਾਹੀਦੇ ਹਨ। ਜੇਕਰ ਕੱਟਣ ਤੋਂ ਬਾਅਦ ਜਮ੍ਹਾਂ ਕਰਨਾ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਪੈਸੇ ਸਿਰਫ਼ ਖ਼ਤਮ ਨਹੀਂ ਹੋ ਜਾਂਦੇ। ਬੈਂਕ ਕੱਟੇ ਗਏ ਪੈਸਿਆਂ ਨੂੰ ਵਾਪਸ ਕਰ ਦਿੰਦਾ ਹੈ। ਉਹ ਵਾਪਸੀ ਹੀ ਰੋਲਬੈਕ (rollback) ਹੈ। ਜੇਕਰ ਦੋਵੇਂ ਕਦਮ ਸਫਲ ਹੁੰਦੇ ਹਨ, ਤਾਂ ਟ੍ਰਾਂਸਫਰ ਕਮਿਟ (commit) ਹੋ ਜਾਂਦਾ ਹੈ, ਜਿਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਨਵੇਂ ਬੈਲੇਂਸ ਸੁਰੱਖਿਅਤ ਤੌਰ 'ਤੇ ਸੇਵ ਹੋ ਗਏ ਹਨ।
ਇਹ 'ਸਭ ਕੁਝ ਜਾਂ ਕੁਝ ਵੀ ਨਹੀਂ' (all-or-nothing) ਵਾਲਾ ਵਿਵਹਾਰ ਹੀ ਤੁਹਾਡੇ ਡੇਟਾ ਨੂੰ ਇਕਸਾਰ (consistent) ਰੱਖਦਾ ਹੈ। ਇਸ ਤੋਂ ਬਿਨਾਂ, ਅਧੂਰੇ ਫੇਲ੍ਹ ਹੋਣ ਕਾਰਨ ਅਧੂਰੇ ਲਿਖੇ ਰਿਕਾਰਡ ਤੁਹਾਡੀਆਂ ਟੇਬਲਾਂ ਵਿੱਚ ਖਿੱਲਰ ਜਾਂਦੇ ਹਨ, ਅਤੇ ਉਹ ਰਿਕਾਰਡ ਤੁਹਾਡੇ ਡਾਟਾਬੇਸ ਵਿੱਚ ਖਰਾਬ ਹੋ ਜਾਂਦੇ ਹਨ ਕਿਉਂਕਿ ਕਿਸੇ ਵੀ ਆਟੋਮੇਟਡ ਪ੍ਰਕਿਰਿਆ ਨੂੰ ਇਹ ਨਹੀਂ ਪਤਾ ਹੁੰਦਾ ਕਿ ਉਹਨਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਤਰੀਕੇ ਨਾਲ ਕਿਵੇਂ ਸਾਫ਼ ਕਰਨਾ ਹੈ।
Laravel ਇਸਨੂੰ ਕਿਵੇਂ ਸੰਭਾਲਦਾ ਹੈ
ਸਾਧਾਰਨ SQL ਵਿੱਚ, ਤੁਸੀਂ ਖੁਦ BEGIN, COMMIT, ਅਤੇ ROLLBACK ਲਿਖੋਗੇ, ਅਤੇ ਹਰ ਸੰਭਵ ਗਲਤੀ (error) ਨੂੰ ਫੜਨ ਦਾ ਧਿਆਨ ਰੱਖੋਗੇ ਤਾਂ ਜੋ ਕੋਈ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਅਧੂਰੀ ਨਾ ਰਹਿ ਜਾਵੇ। Laravel ਉਸ ਸਾਰੇ ਵਾਧੂ ਕੋਡ (boilerplate) ਨੂੰ ਇੱਕ ਸਿੰਗਲ ਮੈਥਡ ਵਿੱਚ ਲਪੇਟ ਦਿੰਦਾ ਹੈ।
ਤੁਸੀਂ DB::transaction() ਨੂੰ ਇੱਕ closure ਪਾਸ ਕਰਦੇ ਹੋ। Laravel ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਸ਼ੁਰੂ ਕਰਦਾ ਹੈ, ਤੁਹਾਡਾ ਕੋਡ ਚਲਾਉਂਦਾ ਹੈ, ਅਤੇ ਜੇਕਰ closure ਬਿਨਾਂ ਕਿਸੇ ਐਕਸੈਪਸ਼ਨ (exception) ਦੇ ਖਤਮ ਹੋ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਇਹ ਆਪਣੇ ਆਪ ਕਮਿਟ ਹੋ ਜਾਂਦਾ ਹੈ। ਜੇਕਰ ਕੁਝ ਵੀ ਫੇਲ੍ਹ ਹੁੰਦਾ ਹੈ, ਤਾਂ Laravel ਐਕਸੈਪਸ਼ਨ ਨੂੰ ਫੜ ਲੈਂਦਾ ਹੈ, ਸਭ ਕੁਝ ਰੋਲਬੈਕ ਕਰ ਦਿੰਦਾ ਹੈ, ਅਤੇ ਗਲਤੀ ਨੂੰ ਦੁਬਾਰਾ ਸੁੱਟਦਾ (rethrow) ਹੈ ਤਾਂ ਜੋ ਤੁਹਾਡੀ ਲੌਗਿੰਗ ਅਤੇ ਐਰਰ ਹੈਂਡਲਿੰਗ ਅਜੇ ਵੀ ਉਮੀਦ ਅਨੁਸਾਰ ਕੰਮ ਕਰ ਸਕੇ।
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
$order = Order::create([/* ... */]);
foreach ($cart->items as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_id' => $item->product_id,
'quantity' => $item->quantity,
]);
Product::find($item->product_id)
->decrement('stock', $item->quantity);
}
Payment::create([
'order_id' => $order->id,
'amount' => $cart->total,
'status' => 'completed',
]);
});
ਜੇਕਰ ਫੋਰਨ ਕੀ (foreign key) ਦੀ ਘਾਟ ਕਾਰਨ ਜਾਂ ਡਾਟਾਬੇਸ ਕਨੈਕਸ਼ਨ ਟੁੱਟਣ ਕਾਰਨ ਪੇਮੈਂਟ ਇੰਸਰਟ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਆਰਡਰ, ਆਰਡਰ ਦੀਆਂ ਆਈਟਮਾਂ, ਅਤੇ ਸਟਾਕ ਵਿੱਚ ਹੋਏ ਬਦਲਾਅ ਸਾਰੇ ਰੱਦ ਹੋ ਜਾਂਦੇ ਹਨ। ਤੁਹਾਡੇ ਕੋਲ ਅਜਿਹਾ ਇਨਵੈਂਟਰੀ ਨਹੀਂ ਰਹੇਗਾ ਜੋ ਬਿਨਾਂ ਕਿਸੇ ਕਾਰਨ ਗਾਇਬ ਹੋ ਗਿਆ ਹੋਵੇ, ਅਤੇ ਤੁਹਾਡੇ ਕੋਲ ਅਜਿਹਾ ਆਰਡਰ ਵੀ ਨਹੀਂ ਰਹੇਗਾ ਜਿਸਦੀ ਸ਼ਿਪਮੈਂਟ ਦੀ ਮੰਗ ਕੀਤੀ ਗਈ ਹੋਵੇ ਪਰ ਉਸਦਾ ਭੁਗਤਾਨ ਨਾ ਕੀਤਾ ਗਿਆ ਹੋਵੇ।
ਇਹ ਤੁਹਾਨੂੰ ਕਿੱਥੇ ਬਚਾਉਂਦਾ ਹੈ
ਕੁਝ ਵਰਕਫਲੋ (workflows) ਪੂਰੀ ਤਰ੍ਹਾਂ ਟ੍ਰਾਂਜੈਕਸ਼ਨਲ ਸੁਰੱਖਿਆ 'ਤੇ ਨਿਰਭਰ ਕਰਦੇ ਹਨ। ਚੈੱਕਆਊਟ ਦੀ ਉਦਾਹਰਣ ਸਭ ਤੋਂ ਸਪੱਸ਼ਟ ਹੈ, ਪਰ ਇਹ ਪੈਟਰਨ ਹਰ ਜਗ੍ਹਾ ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ।
ਯੂਜ਼ਰ ਰਜਿਸਟ੍ਰੇਸ਼ਨ। ਇੱਕ ਯੂਜ਼ਰ ਰੋਅ (row) ਬਣਾਉਣਾ, ਫਿਰ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਰੋਅ, ਫਿਰ ਡਿਫੌਲਟ ਸੈਟਿੰਗਾਂ। ਜੇਕਰ ਵੈਲੀਡੇਸ਼ਨ ਦੇ ਕਿਸੇ ਮਾਮਲੇ ਕਾਰਨ ਪ੍ਰੋਫਾਈਲ ਇੰਸਰਟ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਬਿਨਾਂ ਯੂਜ਼ਰ ਇੱਕ 'ਘੋਸਟ ਅਕਾਊਂਟ' (ghost account) ਬਣ ਜਾਂਦਾ ਹੈ। ਕੋਈ ਵੀ ਪੇਜ ਜੋ ਇਹ ਮੰਨ ਕੇ ਚੱਲਦਾ ਹੈ ਕਿ ਹਰ ਯੂਜ਼ਰ ਕੋਲ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਹੈ, ਉਹ ਕ੍ਰੈਸ਼ ਹੋ ਜਾਵੇਗਾ ਜਾਂ ਟੁੱਟਿਆ ਹੋਇਆ UI ਦਿਖਾਏਗਾ।
ਬਲਕ ਇੰਪੋਰਟਸ। ਇੱਕ CSV ਅਪਲੋਡ ਜੋ ਪੰਜਾਹ ਰਿਕਾਰਡ ਇੰਸਰਟ ਕਰਦਾ ਹੈ, ਉਸਨੂੰ ਪਿੱਛੇ ਪੱਚੀ ਰਿਕਾਰਡ ਨਹੀਂ ਛੱਡਣੇ ਚਾਹੀਦੇ ਕਿਉਂਕਿ ਛੱਠਵੇਂ ਰੋਅ ਵਿੱਚ ਮੈਲਫਾਰਮਡ (malformed) ਮਿਤੀ ਸੀ। ਬੈਚ ਨੂੰ ਇੱਕ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਵਿੱਚ ਲਪੇਟਣ ਨਾਲ ਪੂਰਾ ਇੰਪੋਰਟ ਇੱਕ ਸਾਫ਼ ਇਕਾਈ ਵਜੋਂ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦਾ ਹੈ। ਐਡਮਿਨ ਘੰਟਿਆਂ ਬੱਧੀ ਇਹ ਲੱਭਣ ਦੀ ਬਜਾਏ ਕਿ ਕਿਹੜੀਆਂ ਰੋਅ ਅਧੂਰੀਆਂ ਰਹਿ ਗਈਆਂ ਹਨ, ਫਾਈਲ ਨੂੰ ਠੀਕ ਕਰਦਾ ਹੈ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਦਾ ਹੈ।
**ਇ
ਸਹੀ ਕ੍ਰਮ ਇਹ ਹੈ:
- ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਨੂੰ ਪੂਰਾ ਕਰੋ ਅਤੇ ਲੋੜੀਂਦੀਆਂ ਕਿਸੇ ਵੀ ID ਜਾਂ ਨਤੀਜਿਆਂ ਨੂੰ ਕੈਪਚਰ ਕਰੋ।
- ਫਿਰ ਹੀ ਬਾਹਰੀ ਸਾਈਡ ਇਫੈਕਟਸ (side effects) ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ।
ਉਦਾਹਰਨ ਲਈ, ਕਨਫਰਮੇਸ਼ਨ ਈਮੇਲ ਨੂੰ ਕਮਿਟ (commit) ਤੋਂ ਬਾਅਦ ਕਿਊ (queue) ਕਰੋ, ਇਸਦੇ ਅੰਦਰ ਨਹੀਂ:
$order = DB::transaction(function () {
// database work only
return Order::create([/* ... */]);
});
// Side effects happen after the database state is solid
OrderConfirmationJob::dispatch($order);
ਬਾਹਰੀ ਕਾਲਾਂ ਨੂੰ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਤੋਂ ਬਾਹਰ ਰੱਖਣ ਦਾ ਦੂਜਾ ਕਾਰਨ ਹੈ: ਸਮਾਂ। ਇੱਕ ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਲੌਕ (locks) ਰੱਖਦੀ ਹੈ ਅਤੇ ਡਾਟਾਬੇਸ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰੁੱਝਿਆ ਰੱਖਦੀ ਹੈ। ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਦੇ ਅੰਦਰ ਰਹਿੰਦੇ ਹੋਏ Stripe API ਦੇ ਜਵਾਬ ਲਈ ਤਿੰਨ ਸਕਿੰਟ ਉਡੀਕ ਕਰਨਾ, ਤਿੰਨ ਸਕਿੰਟ ਦਾ ਬੇਲੋੜਾ ਲੌਕ ਸਮਾਂ ਹੈ। ਟ੍ਰਾਂਜੈਕਸ਼ਨ ਨੂੰ ਸੰਖੇਪ ਅਤੇ ਤੇਜ਼ ਰੱਖੋ।
ਇਹ ਬੱਗ (bug) ਕਿਉਂ ਲੁਕਿਆ ਰਹਿੰਦਾ ਹੈ
ਇੱਕ ਸਿੰਗਲ ਯੂਜ਼ਰ ਅਤੇ ਲੋਕਲ ਡਾਟਾਬੇਸ ਵਾਲੀ ਡਿਵੈਲਪਮੈਂਟ ਮਸ਼ੀਨ 'ਤੇ, ਸਬੰਧਤ ਇਨਸਰਟ (inserts) ਲਗਭਗ ਹਮੇਸ਼ਾ ਸਫਲ ਹੋ ਜਾਂਦੇ ਹਨ। ਨੈੱਟਵਰਕ ਸਥਿਰ ਹੁੰਦਾ ਹੈ, ਡਿਸਕ ਕਦੇ ਭਰਦੀ ਨਹੀਂ ਹੈ, ਅਤੇ ਕੋਈ ਹੋਰ ਲੋਡ (load) ਨਹੀਂ ਹੁੰਦਾ। ਕੋਡ ਸਹੀ ਲੱਗਦਾ ਹੈ ਕਿਉਂਕਿ ਇਹ ਆਮ ਤੌਰ 'ਤੇ ਕੰਮ ਕਰਦਾ ਹੈ।
ਪ੍ਰੋਡਕਸ਼ਨ (Production) ਵੱਖਰੀ ਹੁੰਦੀ ਹੈ। ਦੋ ਗਾਹਕ ਬਿਲਕੁਲ ਇੱਕੋ ਮਿਲੀਸਕਿੰਡ ਵਿੱਚ ਆਰਡਰ ਸਬਮਿਟ ਕਰਦੇ ਹਨ। ਡਿਪਲਾਈਮੈਂਟ (deployment) ਦੌਰਾਨ ਇੱਕ ਕਿਊ ਵਰਕਰ (queue worker) ਕੰਮ ਦੇ ਵਿਚਕਾਰ ਹੀ ਰੀਸਟਾਰਟ ਹੋ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਪੇਮੈਂਟ ਪ੍ਰੋਵਾਈਡਰ ਤਿਰਤੀ ਸਕਿੰਟ ਲਈ ਟਾਈਮ ਆਊਟ ਹੋ ਜਾਂਦਾ ਹੈ। ਟ੍ਰਾਂਜੈਕਸ਼ਨਾਂ ਤੋਂ ਬਿਨਾਂ, ਇਹ ਘਟਨਾਵਾਂ ਅਨਾਧਾਰਿਤ (orphan) ਰਿਕਾਰਡ ਅਤੇ ਗਲਤ ਟੋਟਲ ਬਣਾਉਂਦੀਆਂ ਹਨ ਜਿਨ੍ਹਾਂ ਨੂੰ ਲੱਭਣਾ ਬਹੁਤ ਮੁਸ਼ਕਲ ਹੁੰਦਾ ਹੈ। ਸਭ ਤੋਂ ਮਾੜੀ ਗੱਲ ਇਹ ਹੈ ਕਿ ਸਟੈਂਡਰਡ ਫੀਚਰ ਟੈਸਟ (standard feature tests) ਇਨ੍ਹਾਂ ਨੂੰ ਸ਼ਾਇਦ ਹੀ ਕਦੇ ਫੜ ਸਕਦੇ ਹਨ, ਕਿਉਂਕਿ ਫੇਲ੍ਹ ਹੋਣ ਦਾ ਕਾਰਨ ਸਮੇਂ (timing) 'ਤੇ ਨਿਰਭਰ ਕਰਦਾ ਹੈ ਅਤੇ ਇਨਫਰਾਸਟ੍ਰਕਚਰ (infrastructure) ਨਾਲ ਜੁੜਿਆ ਹੁੰਦਾ ਹੈ, ਨਾ ਕਿ ਸਧਾਰਨ ਲੌਜਿਕ ਗਲਤੀਆਂ ਨਾਲ।
ਇਸਨੂੰ ਇੱਕ ਆਦਤ ਬਣਾਓ
DB::transaction() ਗੁੰਝਲਦਾਰਤਾ ਨਹੀਂ ਵਧਾਉਂਦਾ। ਇਹ ਬਾਅਦ ਵਿੱਚ ਅਧੂਰੇ ਡੇਟਾ ਨੂੰ ਸਾਫ਼ ਕਰਨ ਦੀ ਲੁਕੀ ਹੋਈ ਗੁੰਝਲਦਾਰਤਾ ਨੂੰ ਖਤਮ ਕਰਦਾ ਹੈ। ਜੇਕਰ ਡਾਟਾਬੇਸ ਕਾਰਵਾਈਆਂ (operations) ਦਾ ਇੱਕ ਸਮੂਹ ਇਕੱਠਾ ਹੈ, ਤਾਂ ਸ਼ੁਰੂ ਤੋਂ ਹੀ ਉਹਨਾਂ ਨਾਲ ਉਸੇ ਤਰ੍ਹਾਂ ਦਾ ਸਲੂਕ ਕਰੋ। ਤੁਹਾਡੀ ਐਪਲੀਕੇਸ਼ਨ ਲੋਡ ਦੇ ਅਧੀਨ ਸਹੀ ਰਹੇਗੀ, ਤੁਹਾਡੇ ਐਰਰ ਲੌਗ (error logs) ਸਾਫ਼ ਰਹਿਣਗੇ, ਅਤੇ ਤੁਹਾਡਾ ਡਾਟਾਬੇਸ ਅਧੂਰੇ ਰਿਕਾਰਡਾਂ ਦਾ ਕਬਰਸਤਾਨ ਨਹੀਂ ਬਣੇਗਾ।
