Transactions এবং Concurrency Control

টাইপওআরএম (TypeORM) - Web Development

336

TypeORM এ Transactions এবং Concurrency Control

Transactions এবং Concurrency Control হল ডেটাবেসের অত্যন্ত গুরুত্বপূর্ণ ধারণা, যা ডেটা অ্যাক্সেস এবং আপডেটের প্রক্রিয়া সঠিকভাবে পরিচালনা করতে সাহায্য করে। TypeORM-এ, আপনি খুব সহজেই transactions তৈরি করতে পারেন এবং ডেটাবেসে একাধিক অপারেশন একযোগে চালানোর মাধ্যমে ডেটার অখণ্ডতা (data integrity) নিশ্চিত করতে পারেন।

Concurrency Control হল এমন একটি প্রক্রিয়া যার মাধ্যমে একাধিক ব্যবহারকারী বা থ্রেড একই ডেটার উপর একযোগে কাজ করলে ডেটার সমস্যা বা সংঘর্ষ (conflict) এড়ানো হয়। TypeORM-এর মাধ্যমে আপনি optimistic এবং pessimistic locking পদ্ধতি ব্যবহার করে concurrency সমস্যাগুলো নিয়ন্ত্রণ করতে পারেন।

এই গাইডে আমরা TypeORM-এ transactions এবং concurrency control ব্যবহার করার সেরা প্র্যাকটিস সম্পর্কে বিস্তারিত আলোচনা করব।


১. Transactions

একটি transaction হলো একটি ডেটাবেস অপারেশনগুলোর গ্রুপ, যেগুলি একযোগে সম্পাদিত হয়। একটি ট্রানজেকশনের মধ্যে একাধিক ডেটাবেস অপারেশন যেমন INSERT, UPDATE, বা DELETE অন্তর্ভুক্ত থাকতে পারে এবং এগুলোর সবগুলো সফলভাবে সম্পন্ন হলে ডেটাবেসে সেই পরিবর্তনগুলি স্থায়ী হয়। যদি কোনো একটি অপারেশন ব্যর্থ হয়, তাহলে পুরো transactionটি বাতিল (rollback) হয়ে যাবে, এবং ডেটাবেস আগের অবস্থায় ফিরে যাবে।

TypeORM-এ Transaction ব্যবহার

TypeORM-এ একটি transaction পরিচালনা করতে, আপনি manager.transaction() ব্যবহার করতে পারেন। এটি একটি QueryRunner ব্যবহার করে transaction পরিচালনা করে, যা ডেটাবেসে একাধিক অপারেশন সফলভাবে পরিচালিত হবে কিনা তা নিশ্চিত করে।

উদাহরণ:

import { createConnection, getManager } from "typeorm";
import { User } from "./entity/User";
import { Post } from "./entity/Post";

createConnection().then(async connection => {
  const manager = getManager();

  // Start a new transaction
  await manager.transaction(async transactionalEntityManager => {
    // Create a new user
    const user = new User();
    user.name = "John Doe";
    user.email = "john.doe@example.com";
    await transactionalEntityManager.save(user);

    // Create a new post for the user
    const post = new Post();
    post.title = "New Post by John";
    post.content = "This is a post created inside a transaction";
    post.user = user;
    await transactionalEntityManager.save(post);

    // If no errors occur, the transaction is committed automatically
  }).catch(error => {
    // If an error occurs, the transaction is rolled back automatically
    console.error("Error during transaction:", error);
  });

}).catch(error => console.log(error));

এখানে, আমরা transactionalEntityManager ব্যবহার করে দুটি ডেটাবেস অপারেশন (User এবং Post তৈরি) একযোগে সম্পন্ন করছি। যদি কোন একটি অপারেশন ব্যর্থ হয়, তাহলে সমস্ত অপারেশন রোলব্যাক হবে এবং ডেটাবেস আগের অবস্থায় ফিরে যাবে।


২. Concurrency Control

Concurrency Control হল একটি প্রক্রিয়া যার মাধ্যমে একাধিক ব্যবহারকারী বা থ্রেড একসাথে ডেটাবেসে একাধিক অপারেশন সম্পাদন করলে ডেটার অখণ্ডতা নিশ্চিত করা হয়। TypeORM-এ দুইটি সাধারণ concurrency control পদ্ধতি রয়েছে:

  1. Optimistic Locking (অপটিমিস্টিক লকিং)
  2. Pessimistic Locking (পেসিমিস্টিক লকিং)

Optimistic Locking

Optimistic Locking হল একটি কৌশল যেখানে ডেটা ম্যানিপুলেশন করার সময়, ডেটার পরিবর্তন হওয়ার সম্ভাবনা সম্পর্কে বিশ্বাস করা হয়, তবে একাধিক ব্যবহারকারী একই ডেটা আপডেট করার চেষ্টা করলে তা চেক করা হয় এবং যদি কোনো কনফ্লিক্ট থাকে তবে ট্রানজেকশনটি বাতিল (rollback) হয়ে যায়।

TypeORM-এ optimistic locking সাধারণত version column (যেমন version বা timestamp) ব্যবহার করে কাজ করে। যখন ডেটা আপডেট করা হয়, তখন টেবিলের version ফিল্ড চেক করা হয়। যদি version পরিবর্তিত হয়ে থাকে, তবে ট্রানজেকশনটি ব্যর্থ হবে।

Optimistic Locking উদাহরণ:

import { Entity, PrimaryGeneratedColumn, Column, VersionColumn } from "typeorm";

@Entity()
export class Product {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  price: number;

  @VersionColumn()
  version: number; // version column for optimistic locking
}

এখানে, version কলামটি optimistic locking প্রয়োগ করতে ব্যবহৃত হবে।

আপনি যখন Product আপডেট করবেন, TypeORM স্বয়ংক্রিয়ভাবে version কলাম চেক করবে এবং যদি version পরিবর্তিত হয়ে থাকে, তাহলে আপডেট ট্রানজেকশনটি ব্যর্থ হবে।


Pessimistic Locking

Pessimistic Locking হল একটি কৌশল যেখানে ডেটার উপর একটি লক প্রয়োগ করা হয়, যাতে অন্য কেউ সেই ডেটার উপর কাজ না করতে পারে যতক্ষণ না প্রথম ব্যবহারকারী তার কাজ সম্পূর্ণ না করে। TypeORM-এ pessimistic locking forUpdate() বা forShare() ব্যবহার করে করা হয়, যা ডেটার উপর লক প্রয়োগ করে।

Pessimistic Locking উদাহরণ:

import { createConnection, getManager } from "typeorm";
import { Product } from "./entity/Product";

createConnection().then(async connection => {
  const manager = getManager();

  // Start a transaction with pessimistic locking
  await manager.transaction(async transactionalEntityManager => {
    const product = await transactionalEntityManager
      .createQueryBuilder(Product, "product")
      .setLock("pessimistic_write") // Apply pessimistic lock
      .where("product.id = :id", { id: 1 })
      .getOne();

    if (product) {
      // Update the product's price
      product.price += 10;
      await transactionalEntityManager.save(product);
    }
  }).catch(error => {
    console.error("Error during transaction:", error);
  });

}).catch(error => console.log(error));

এখানে, setLock("pessimistic_write") ব্যবহার করে pessimistic locking প্রয়োগ করা হয়েছে, যা Product টেবিলের রেকর্ডের উপর একটি লেখার লক প্রয়োগ করবে।


সারাংশ

Transactions এবং Concurrency Control হল ডেটাবেস ব্যবস্থাপনার গুরুত্বপূর্ণ অংশ, যা TypeORM-এ ডেটা অ্যাক্সেস এবং একাধিক অপারেশনের কার্যকারিতা নিশ্চিত করতে সাহায্য করে। Transactions ডেটাবেসের একাধিক অপারেশন একযোগে সম্পাদন করার জন্য ব্যবহৃত হয়, যেখানে আপনি নিশ্চিত করেন যে সমস্ত অপারেশন সফল হলে শুধুমাত্র পরিবর্তনগুলি স্থায়ী হবে, অন্যথায় সেগুলি রোলব্যাক হবে। Concurrency Control নিশ্চিত করে যে একাধিক ব্যবহারকারী একসাথে ডেটাবেসে কাজ করলে কোনো ডেটার সমস্যা বা কনফ্লিক্ট না হয়। TypeORM-এ আপনি Optimistic Locking এবং Pessimistic Locking এর মাধ্যমে concurrency সমস্যা নিয়ন্ত্রণ করতে পারেন।

Content added By

Transaction কি?

Transaction হল একটি ডেটাবেস অপারেশন বা কাজের একটি গ্রুপ যা একত্রে সম্পন্ন হয়। অর্থাৎ, একটি transaction-এ একাধিক ডেটাবেস অপারেশন থাকে এবং এদের সকল অপারেশন সফলভাবে সম্পন্ন না হওয়া পর্যন্ত একে পুরোপুরি সম্পন্ন বা বাতিল করা হয় না। Transaction ব্যবহৃত হয় ডেটাবেসের ACID (Atomicity, Consistency, Isolation, Durability) গুণাবলী নিশ্চিত করার জন্য।

  • Atomicity (অ্যাটমিকতা): একটি transaction সম্পূর্ণভাবে সফল হলে সব কিছু কমিট হবে, আর যদি কিছু ত্রুটি ঘটে তবে সব কিছু রিভার্ট হবে (roll back)।
  • Consistency (সঙ্গতি): একটি transaction সম্পূর্ণভাবে ডেটাবেসের সঠিক অবস্থায় রাখবে।
  • Isolation (বিচ্ছিন্নতা): প্রতিটি transaction আলাদা আলাদা কাজ করবে এবং অন্য কোন transaction এর কাজকে প্রভাবিত করবে না।
  • Durability (স্থিতিশীলতা): একবার একটি transaction সফলভাবে কমিট হলে, তা পরবর্তী সময়ে পরিবর্তন হবে না এবং সিস্টেম ক্র্যাশ বা ত্রুটির পরও অপরিবর্তিত থাকবে।

TypeORM-এ Transactions এর প্রয়োজনীয়তা

TypeORM-এ transactions ব্যবহৃত হয় যখন একাধিক ডেটাবেস অপারেশন একত্রে করা হয় এবং আপনি নিশ্চিত করতে চান যে, এগুলি একসাথে সফলভাবে সম্পন্ন হবে অথবা কোনো কারণে সমস্যা হলে সেগুলি প্রত্যাহার (rollback) হয়ে যাবে। TypeORM transactions নিশ্চিত করে যে ডেটাবেসের অবস্থা সঠিক থাকে এবং কোনো ডেটাবেস অপ্রত্যাশিত অবস্থায় চলে না।

উদাহরণস্বরূপ, যখন আপনি একটি বিলিং সিস্টেম পরিচালনা করছেন, এবং আপনি একটি ট্রানজেকশন তৈরি করতে চান যা দুটি ডেটাবেস অপারেশনকে একসাথে সম্পন্ন করবে:

  1. একটি অর্ডার তৈরি করুন।
  2. একটি পেমেন্ট প্রক্রিয়া করুন।

এখন যদি পেমেন্ট সফলভাবে সম্পন্ন না হয়, তবে আপনার অর্ডারটি তৈরি না হয়ে, সব কিছু rollback হয়ে যাবে। এইভাবে, একটি সফল পেমেন্ট ছাড়া কোনো অর্ডার তৈরি হবে না।


TypeORM-এ Transaction ব্যবহারের উপকারিতা

  1. ডেটার অখণ্ডতা রক্ষা: Transactions ব্যবহারের মাধ্যমে ডেটাবেসের অবস্থা সর্বদা সঠিক থাকে। কোনো একটি অপারেশন ব্যর্থ হলে, পুরো ট্রানজেকশন রিভার্ট (rollback) হয়ে যাবে।
  2. ডেটা সিঙ্ক্রোনাইজেশন: যখন একাধিক অপারেশন একে অপরের উপর নির্ভরশীল, তখন ট্রানজেকশন ব্যবহার করা হয় যাতে সমস্ত অপারেশন একসাথে সম্পন্ন হয়।
  3. ব্যর্থতার পরে অটোমেটিক রোলব্যাক: যদি একটি অপারেশন ব্যর্থ হয়, তবে পুরোটাই রোলব্যাক হবে, ফলে ডেটাবেসের অবস্থার কোনো সমস্যা হবে না।
  4. পারফরম্যান্স অপটিমাইজেশন: একাধিক অপারেশন একসাথে এক transaction-এ করা হলে, এটি ডেটাবেসের উপর কম লোড ফেলে এবং পারফরম্যান্সে উন্নতি ঘটায়।

TypeORM-এ Transaction ব্যবহারের পদ্ধতি

TypeORM-এ transaction ব্যবহারের জন্য QueryRunner ব্যবহার করা হয়। QueryRunner একটি ক্লাস যা একটি একক ট্রানজেকশন তৈরি করে এবং সব ডেটাবেস অপারেশন একসাথে পরিচালনা করে।

উদাহরণ:

import { createConnection, getManager } from "typeorm";
import { User } from "./entity/User";
import { Post } from "./entity/Post";

createConnection().then(async connection => {
  const queryRunner = connection.createQueryRunner();

  // Start a transaction
  await queryRunner.startTransaction();

  try {
    // Perform the operations in the transaction
    const user = new User();
    user.name = "John Doe";
    await queryRunner.manager.save(user); // Save user using the query runner

    const post = new Post();
    post.title = "My first post";
    post.user = user;
    await queryRunner.manager.save(post); // Save post using the query runner

    // Commit the transaction if everything is successful
    await queryRunner.commitTransaction();
  } catch (error) {
    // If any operation fails, rollback the transaction
    await queryRunner.rollbackTransaction();
    console.log("Transaction failed and rolled back");
  } finally {
    // Release the query runner, whether the transaction was successful or not
    await queryRunner.release();
  }
}).catch(error => console.log(error));

এখানে, আমরা QueryRunner ব্যবহার করে একটি ট্রানজেকশন শুরু করছি। সমস্ত ডেটাবেস অপারেশন (যেমন save() ফাংশন) আমরা queryRunner.manager এর মাধ্যমে করছি। যদি সব কিছু সফলভাবে হয়, তবে আমরা commitTransaction() কল করি। অন্যথায়, যদি কোনো ত্রুটি ঘটে, তবে rollbackTransaction() কল করি, যাতে সমস্ত পরিবর্তন রিভার্ট হয়।


সারাংশ

Transaction TypeORM-এ একটি অত্যন্ত গুরুত্বপূর্ণ কৌশল যা একাধিক ডেটাবেস অপারেশনকে একত্রে পরিচালনা করতে সহায়তা করে। এটি ACID গুণাবলী রক্ষা করে এবং ডেটাবেসের অবস্থাকে সঠিক রাখে। TypeORM-এ QueryRunner ব্যবহার করে আপনি সহজেই ট্রানজেকশন শুরু, পরিচালনা এবং রোলব্যাক করতে পারেন। ট্রানজেকশন ব্যবহারের মাধ্যমে আপনি নিশ্চিত করতে পারেন যে, আপনার অ্যাপ্লিকেশনের সমস্ত ডেটাবেস অপারেশন একত্রে সফলভাবে সম্পন্ন হবে এবং কোনো ত্রুটি ঘটলে সমস্ত পরিবর্তন বাতিল হয়ে যাবে।

Content added By

TypeORM এ Transactions

Transactions হল ডেটাবেসে একাধিক অপারেশন গ্রুপ করার একটি পদ্ধতি, যেখানে সব অপারেশন একত্রে সফলভাবে সম্পন্ন হলে এগুলো কমিট (commit) করা হয়, আর যদি কোনো একটি অপারেশন ব্যর্থ হয়, তবে সব অপারেশন রোলব্যাক (rollback) হয়ে যায়। এটি নিশ্চিত করে যে ডেটাবেসে কোনো আংশিক বা অসম্পূর্ণ পরিবর্তন না ঘটে এবং ডেটাবেসের অখণ্ডতা বজায় থাকে।

TypeORM-এ ট্রান্সেকশন ব্যবহারের জন্য QueryRunner ব্যবহার করা হয়, যা একটি সেশন তৈরি করে এবং একাধিক কুয়েরি একসাথে পরিচালনা করতে দেয়। এই সেশনটি ট্রান্সেকশন শুরু, কমিট বা রোলব্যাক করতে সহায়তা করে।


১. Transaction শুরু করা

TypeORM-এ ট্রান্সেকশন শুরু করতে QueryRunner ব্যবহার করতে হয়। এর মাধ্যমে আমরা ডেটাবেসের উপর একাধিক অপারেশন একত্রে পরিচালনা করতে পারি এবং পরে একটি নির্দিষ্ট সময় সব অপারেশন একযোগে কমিট বা রোলব্যাক করতে পারি।

Transaction শুরু করার উদাহরণ:

import { createConnection, getManager } from "typeorm";
import { User } from "./entity/User";
import { Post } from "./entity/Post";

createConnection().then(async connection => {
  const queryRunner = connection.createQueryRunner();

  // Start a transaction
  await queryRunner.startTransaction();
  
  try {
    // Create new user
    const user = new User();
    user.name = "John Doe";
    user.email = "john@example.com";
    await queryRunner.manager.save(user);

    // Create new post related to the user
    const post = new Post();
    post.title = "First Post";
    post.user = user;
    await queryRunner.manager.save(post);

    // Commit the transaction
    await queryRunner.commitTransaction();
    console.log("Transaction committed!");
  } catch (error) {
    // If any error occurs, rollback the transaction
    await queryRunner.rollbackTransaction();
    console.log("Transaction rolled back due to error!");
  } finally {
    // Release the query runner
    await queryRunner.release();
  }
}).catch(error => console.log(error));

এখানে, আমরা QueryRunner ব্যবহার করে একটি ট্রান্সেকশন শুরু করেছি, এর মধ্যে দুটি অপারেশন করেছি (একটি User তৈরি এবং একটি Post তৈরি), এবং শেষের দিকে যদি সব কিছু সঠিকভাবে চলে তাহলে commitTransaction() ব্যবহার করে কমিট করেছি। কোনো ত্রুটি ঘটলে rollbackTransaction() ব্যবহার করে রোলব্যাক করেছি।


২. Commit এবং Rollback

Commit:

একবার সমস্ত অপারেশন সফলভাবে সম্পন্ন হলে, commitTransaction() ব্যবহার করে ডেটাবেসে সমস্ত পরিবর্তন স্থায়ী করা হয়।

await queryRunner.commitTransaction();

Rollback:

যদি কোনো অপারেশন ব্যর্থ হয় বা ত্রুটি ঘটে, তবে rollbackTransaction() ব্যবহার করে সমস্ত পরিবর্তন পূর্বাবস্থায় ফিরিয়ে আনা হয়।

await queryRunner.rollbackTransaction();

৩. Multiple Operations with Transaction

TypeORM-এ একাধিক অপারেশন একসাথে একটি ট্রান্সেকশনে রাখা যেতে পারে। এতে যদি কোনো একটি অপারেশন ব্যর্থ হয়, তবে সমস্ত অপারেশন রোলব্যাক করা হবে। নিচে একাধিক অপারেশন পরিচালনার উদাহরণ দেওয়া হলো:

Multiple Operations Example:

import { createConnection } from "typeorm";
import { User } from "./entity/User";
import { Post } from "./entity/Post";

createConnection().then(async connection => {
  const queryRunner = connection.createQueryRunner();

  // Start a transaction
  await queryRunner.startTransaction();
  
  try {
    // Create a new user
    const user = new User();
    user.name = "Jane Doe";
    user.email = "jane@example.com";
    await queryRunner.manager.save(user);

    // Create two posts related to the user
    const post1 = new Post();
    post1.title = "First Post by Jane";
    post1.user = user;
    await queryRunner.manager.save(post1);

    const post2 = new Post();
    post2.title = "Second Post by Jane";
    post2.user = user;
    await queryRunner.manager.save(post2);

    // Commit the transaction
    await queryRunner.commitTransaction();
    console.log("All changes have been committed!");
  } catch (error) {
    // Rollback the transaction if any error occurs
    await queryRunner.rollbackTransaction();
    console.log("An error occurred, transaction rolled back!");
  } finally {
    // Release the query runner
    await queryRunner.release();
  }
}).catch(error => console.log(error));

এখানে আমরা দুটি Post তৈরি করেছি, তবে যেহেতু সব অপারেশন একসাথে একটি ট্রান্সেকশনে রাখা হয়েছে, কোনো ত্রুটি ঘটলে সমস্ত পরিবর্তন রোলব্যাক হয়ে যাবে।


৪. Nested Transactions

TypeORM সরাসরি nested transactions সমর্থন করে না, তবে আপনি যদি nested ট্রান্সেকশনের মতো কিছু বাস্তবায়ন করতে চান, তবে আপনি sub-transactions তৈরি করতে পারেন যেখানে একটি মূল ট্রান্সেকশনে সাব-ট্রান্সেকশন অপারেশন থাকে। তবে, এটি সাধারণত queryRunner এর মাধ্যমে করা হয় এবং সাব-ট্রান্সেকশন পরিচালনা করার জন্য বিভিন্ন স্তরে commitTransaction() এবং rollbackTransaction() কল করা হতে পারে।


৫. Transaction Performance Considerations

যখন আপনি একটি বড় ট্রান্সেকশন পরিচালনা করছেন, তখন কিছু বিষয় মাথায় রাখা গুরুত্বপূর্ণ:

  • ডেটাবেসের অখণ্ডতা (Integrity): সব ট্রান্সেকশনের মধ্যে সম্পর্ক থাকা উচিত, যাতে কোন একটি অপারেশন ব্যর্থ হলে সব পরিবর্তন পূর্বাবস্থায় ফিরে যায়।
  • পারফরম্যান্স: একাধিক অপারেশন চালানোর জন্য ট্রান্সেকশন ব্যবহারের সময় পারফরম্যান্স অ্যাকাউন্টে রাখা উচিত, বিশেষত বড় ডেটা সেটে।
  • অপারেশন সিকোয়েন্স (Operation Sequence): ট্রান্সেকশনে কোন অপারেশন আগে এবং কোন অপারেশন পরে আসবে তা সঠিকভাবে পরিকল্পনা করা উচিত।

সারাংশ

TypeORM-এ Transactions ব্যবহারের মাধ্যমে আপনি ডেটাবেস অপারেশনগুলো একত্রে এবং একযোগে পরিচালনা করতে পারেন, যা ডেটাবেসের অখণ্ডতা বজায় রাখতে সহায়তা করে। Commit এবং Rollback ব্যবহার করে আপনি সফল অপারেশনগুলো সংরক্ষণ এবং ব্যর্থ অপারেশনগুলো পুনরুদ্ধার করতে পারেন। QueryRunner এর মাধ্যমে ট্রান্সেকশন পরিচালনা করা হয় এবং Transaction ব্যবহারের সময় সঠিক পরিকল্পনা ও কার্যকারিতা নিশ্চিত করতে হবে। TypeORM-এ ট্রান্সেকশন ব্যবহারের মাধ্যমে ডেটাবেসে নিরাপদ এবং স্থিতিশীল পরিবর্তন করা সম্ভব হয়।

Content added By

TypeORM এ Optimistic এবং Pessimistic Locking

Locking হল একটি প্রক্রিয়া যেখানে একাধিক ইউজার বা থ্রেড যখন একই ডেটাবেস রেকর্ডের উপর কাজ করতে যায়, তখন সেই ডেটার নিরাপত্তা এবং সঠিকতা নিশ্চিত করতে লকিং ব্যবহার করা হয়।

TypeORM এ, Optimistic Locking এবং Pessimistic Locking দুটি পদ্ধতি রয়েছে যা ডেটাবেসে Concurrency Control বা একাধিক ইউজারের মধ্যে ডেটার কনকারেন্ট এক্সেস নিয়ন্ত্রণ করতে ব্যবহৃত হয়। এই দুটি পদ্ধতির মধ্যে প্রধান পার্থক্য হলো তাদের লকিং কৌশল এবং ব্যবহারের সময়কাল।


১. Optimistic Locking

Optimistic Locking একটি কৌশল যেখানে ডেটার উপর লক প্রয়োগ করা হয় না, বরং ডেটা ফেচ করার সময় একটি version ফিল্ড ব্যবহার করা হয়। যখন ইউজার বা থ্রেড ডেটা আপডেট করতে যায়, তখন সে একটি চেক করে দেখে যে ডেটা আর পরিবর্তিত হয়নি কি না (version চেক করে)। যদি ডেটা পরিবর্তিত না হয়ে থাকে, তাহলে পরিবর্তন করা যায়, না হলে একটি কনফ্লিক্টের বার্তা প্রদান করা হয়।

Optimistic Locking সাধারণত উচ্চ transaction volume এবং low contention সিচুয়েশনে ব্যবহৃত হয়, যেখানে একাধিক ইউজার একই সময়ে একাধিক রেকর্ডের সাথে কাজ করে, তবে খুব কমই একে অপরের সাথে সংঘর্ষ হয়।

Optimistic Locking এর ব্যবহার:

TypeORM এ Optimistic Locking ব্যবহার করতে, আপনি একটি version ফিল্ড তৈরি করবেন, যেটি প্রতিবার রেকর্ড আপডেট করার সময় বৃদ্ধি পাবে। প্রতিবার আপডেট করার আগে, TypeORM চেক করবে যে রেকর্ডের version আগের মতো আছে কি না।

উদাহরণ:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class Product {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  price: number;

  @Column()
  version: number;  // Version column for optimistic locking
}

এখানে, version ফিল্ডটি প্রতি আপডেটে বৃদ্ধি পাবে। TypeORM যখন একটি রেকর্ড আপডেট করবে, তখন এটি চেক করবে যে বর্তমান version ফিল্ডটি আগের মতো রয়েছে কি না।

Update Example:

const productRepository = connection.getRepository(Product);
const product = await productRepository.findOne({ where: { id: 1 } });

product.price = 100;

// Optimistic Locking: Check if version is still the same
await productRepository.save(product);

এখানে, version ফিল্ডটি TypeORM দ্বারা স্বয়ংক্রিয়ভাবে পরিচালিত হয় এবং যদি কোনো কনফ্লিক্ট পাওয়া যায়, তাহলে OptimisticLockVersionMismatchError ফেলা হবে।


২. Pessimistic Locking

Pessimistic Locking হল একটি কৌশল যেখানে ডেটার উপর লক প্রয়োগ করা হয় যাতে অন্য কোনো ইউজার বা থ্রেড ডেটাকে এক্সেস বা পরিবর্তন করতে না পারে। এটি সাধারণত high contention সিচুয়েশনে ব্যবহৃত হয়, যেখানে একাধিক ইউজার একই ডেটার সাথে একযোগভাবে কাজ করে এবং সংঘর্ষের সম্ভাবনা বেশি থাকে।

Pessimistic Locking ডেটার ওপর সরাসরি লক প্রয়োগ করে, যাতে অন্য ইউজার সেই ডেটা পরিবর্তন করতে না পারে যতক্ষণ না বর্তমান থ্রেড ডেটাটি সম্পূর্ণভাবে ব্যবহার ও আপডেট করে।

Pessimistic Locking এর ব্যবহার:

TypeORM-এ Pessimistic Locking ব্যবহার করার জন্য lock() মেথড ব্যবহার করতে হয়। এই মেথড ডেটা লক করতে সাহায্য করে, যার মাধ্যমে কোনো থ্রেড বা ইউজার একসাথে একাধিক রেকর্ড বা একক রেকর্ডে কাজ করতে পারে।

উদাহরণ:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class Product {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  price: number;
}

এখানে, Product এন্টিটির রেকর্ড লক করতে lock() ব্যবহার করা যাবে।

Select with Pessimistic Lock:

const productRepository = connection.getRepository(Product);

// Pessimistic Locking: Lock the record for update
const product = await productRepository.findOne({
  where: { id: 1 },
  lock: { mode: "pessimistic_write" }
});

product.price = 200;

// Save the product after modifying the locked record
await productRepository.save(product);

এখানে, lock: { mode: "pessimistic_write" } ব্যবহার করে আমরা Pessimistic Locking প্রয়োগ করেছি, যার মাধ্যমে Product রেকর্ডটি আপডেট হওয়ার আগ পর্যন্ত অন্য ইউজার বা থ্রেড এটিকে পরিবর্তন করতে পারবে না।

Pessimistic Locking এর ধরন:

  • pessimistic_read: রেকর্ডটি শুধু পড়ার জন্য লক করা হয়।
  • pessimistic_write: রেকর্ডটি পড়া এবং লেখার জন্য লক করা হয়, অন্য কোনো থ্রেড বা ইউজার এই রেকর্ডের উপর কাজ করতে পারবে না।

সারাংশ

Optimistic Locking এবং Pessimistic Locking দুটি ভিন্ন পদ্ধতি, যা ডেটাবেসের সাথে একাধিক থ্রেড বা ইউজারের এক্সেস কন্ট্রোল করতে সাহায্য করে।

  • Optimistic Locking: ডেটার উপর লক প্রয়োগ না করে একটি version ফিল্ড ব্যবহার করে সংঘর্ষ চেক করা হয়। এটি সাধারণত কম সংঘর্ষ এবং উচ্চ কর্মক্ষমতার জন্য উপযুক্ত।
  • Pessimistic Locking: ডেটার উপর সরাসরি লক প্রয়োগ করে, অন্য থ্রেড বা ইউজারকে ডেটার সাথে কাজ করতে বাধা দেয় যতক্ষণ না বর্তমান থ্রেড ডেটার অপারেশন সম্পন্ন করে।

TypeORM এ এই দুটি কৌশল ব্যবহার করে আপনি আপনার অ্যাপ্লিকেশন বা ডেটাবেসে Concurrency Control প্রক্রিয়া দক্ষভাবে পরিচালনা করতে পারেন। Optimistic Locking কম সংঘর্ষের ক্ষেত্রে এবং Pessimistic Locking উচ্চ সংঘর্ষের পরিস্থিতিতে কার্যকরীভাবে কাজ করে।

Content added By

Concurrency Issues: একটি পরিচিতি

Concurrency Issues হল এমন পরিস্থিতি যেখানে একাধিক প্রক্রিয়া বা থ্রেড একে অপরের সাথে একযোগে কাজ করে এবং কখনও কখনও তাদের মধ্যে সংঘর্ষ (conflict) সৃষ্টি হয়, যেমন একই ডেটা একাধিক বার পরিবর্তন করা। ডেটাবেস অ্যাপ্লিকেশনগুলির ক্ষেত্রে, concurrency issues সাধারণত ঘটে যখন একাধিক ব্যবহারকারী বা প্রসেস একই সময়ে ডেটাবেসের একটি রেকর্ড বা টেবিলের উপর কাজ করার চেষ্টা করে।

TypeORM ব্যবহারের সময়, এই ধরনের সমস্যা সমাধান করা অত্যন্ত গুরুত্বপূর্ণ, কারণ concurrency issues ডেটার অপ্রত্যাশিত পরিবর্তন, তথ্য হারানো বা টেবিলের ডাটা অখণ্ডতা ক্ষতিগ্রস্ত করতে পারে। সুতরাং, টাইপওআরএমে concurrency control এবং data integrity রক্ষা করা প্রয়োজন।

এই গাইডে, আমরা TypeORM-এ concurrency issues মোকাবেলা করার জন্য বিভিন্ন পদ্ধতি এবং Best Practices নিয়ে আলোচনা করব।


Concurrency Issues Types

প্রথমে, concurrency issues এর কিছু সাধারণ ধরন দেখা যাক:

  1. Lost Update: দুটি প্রক্রিয়া একই ডেটা একসাথে পরিবর্তন করে, ফলে একটি পরিবর্তন হারিয়ে যায় এবং অন্য একটি পরিবর্তন প্রাধান্য পায়।
  2. Temporary Inconsistency: একাধিক প্রক্রিয়া ডেটা পড়ছে এবং পরিবর্তন করছে, যার ফলে ডেটাবেস সাময়িকভাবে অস্থির অবস্থায় থাকে।
  3. Deadlock: একাধিক প্রক্রিয়া পরস্পরের জন্য অপেক্ষা করতে থাকে, যেমন দুইটি ট্রানজেকশন একে অপরের লক করা রিসোর্সের জন্য অপেক্ষা করছে।

Concurrency Issues সমাধান করার কৌশল

TypeORM-এ Concurrency Issues সমাধান করতে সাধারণত তিনটি প্রধান কৌশল ব্যবহার করা হয়: Optimistic Locking, Pessimistic Locking, এবং Database Transactions


১. Optimistic Locking

Optimistic Locking হল একটি কৌশল যেখানে আমরা ধরে নিই যে, একাধিক থ্রেড একই সময়ে একই রেকর্ডে কাজ করার চেষ্টা করবে না। তবে, যদি এমন কিছু ঘটে, তবে এটি একটি ভুল বা conflict ঘটাবে, এবং সেই অবস্থায় আপডেট ব্যর্থ হবে।

TypeORM-এ Optimistic Locking এর জন্য, সাধারণত versioning ব্যবহৃত হয়। এক্ষেত্রে, একটি version ফিল্ড প্রতিটি রেকর্ডে রাখা হয় এবং যে কোনো থ্রেড বা ব্যবহারকারী রেকর্ডটি আপডেট করার আগে তার version নম্বর যাচাই করে।

উদাহরণ: Optimistic Locking

  1. Entity এ version ফিল্ড যোগ করা:
import { Entity, PrimaryGeneratedColumn, Column, VersionColumn } from "typeorm";

@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column()
  content: string;

  @VersionColumn()  // version column for optimistic locking
  version: number;
}

এখানে, @VersionColumn() ডেকোরেটরটি রেকর্ডের প্রতিটি আপডেটের সময় version নম্বর আপডেট করবে।

  1. ডেটা আপডেট করার সময় version চেক করা:
import { getRepository } from "typeorm";
import { Post } from "./entity/Post";

async function updatePost(id: number, newTitle: string, newContent: string) {
  const postRepository = getRepository(Post);

  const post = await postRepository.findOne(id);
  if (!post) {
    throw new Error("Post not found");
  }

  post.title = newTitle;
  post.content = newContent;

  // Optimistic Locking check
  const result = await postRepository.save(post).catch(err => {
    if (err.code === "23505") { // Constraint violation due to version conflict
      throw new Error("The post has been modified by another user.");
    }
    throw err;
  });

  console.log("Post updated:", result);
}

এখানে, save() মেথড দিয়ে ডেটা আপডেট করা হয় এবং যদি version mismatch ঘটে, তখন error ধরা হয় এবং আপডেট ব্যর্থ হয়ে যায়।


২. Pessimistic Locking

Pessimistic Locking হল এমন একটি কৌশল যেখানে ডেটা পরিবর্তন করার সময় রেকর্ড বা রিসোর্সের উপর লক বসানো হয়। এটি ডেটার উপর একাধিক ব্যবহারকারীর অ্যাক্সেস নিয়ন্ত্রণ করে। সাধারণত getRepository().lock() ব্যবহার করা হয় যাতে একাধিক থ্রেড একই সময়ে একাধিক পরিবর্তন না করতে পারে।

উদাহরণ: Pessimistic Locking

import { getRepository } from "typeorm";
import { Post } from "./entity/Post";

async function updatePostWithLock(id: number, newTitle: string, newContent: string) {
  const postRepository = getRepository(Post);

  const post = await postRepository.findOne(id, { lock: { mode: "pessimistic_write" } });
  if (!post) {
    throw new Error("Post not found");
  }

  post.title = newTitle;
  post.content = newContent;

  await postRepository.save(post);

  console.log("Post updated with pessimistic locking:", post);
}

এখানে, pessimistic_write লক ব্যবহার করা হয়েছে, যার ফলে একটি থ্রেড যখন রেকর্ডটি আপডেট করছে, তখন অন্য থ্রেডরা সেই রেকর্ডে কোনো পরিবর্তন করতে পারবে না যতক্ষণ না প্রথম থ্রেড কাজটি শেষ করে।


৩. Transactions

Transactions হল একটি অত্যন্ত গুরুত্বপূর্ণ কৌশল যা ডেটাবেসের সঠিকতা এবং অখণ্ডতা নিশ্চিত করতে সাহায্য করে। একটি ট্রানজেকশন হল একাধিক SQL অপারেশন যা একটি অ্যাটমিক ইউনিট হিসেবে কাজ করে। একাধিক অপারেশন যখন একসাথে কাজ করে, তখন ACID (Atomicity, Consistency, Isolation, Durability) বৈশিষ্ট্যগুলির সাথে এটি সম্পন্ন হয়।

TypeORM-এ transactions ব্যবহারের মাধ্যমে আপনি নিশ্চিত করতে পারেন যে, যদি কোনো অপারেশন ব্যর্থ হয়, তবে পুরো ট্রানজেকশনটি রোলব্যাক করা হবে এবং ডেটাবেসের অখণ্ডতা বজায় থাকবে।

উদাহরণ: Transactions ব্যবহার করা

import { getManager } from "typeorm";
import { Post } from "./entity/Post";

async function updatePostInTransaction(id: number, newTitle: string, newContent: string) {
  const manager = getManager();

  await manager.transaction(async (transactionalEntityManager) => {
    const post = await transactionalEntityManager.findOne(Post, id);
    if (!post) {
      throw new Error("Post not found");
    }

    post.title = newTitle;
    post.content = newContent;

    await transactionalEntityManager.save(Post, post);
  });

  console.log("Post updated successfully inside transaction");
}

এখানে, manager.transaction() ব্যবহার করে একটি ট্রানজেকশন শুরু করা হয়েছে এবং তার মধ্যে সমস্ত অপারেশন নিশ্চিত করা হয়েছে। যদি কোনো ত্রুটি ঘটে, তাহলে সম্পূর্ণ ট্রানজেকশন রোলব্যাক হবে।


৪. Deadlock Issues এবং সমাধান

Deadlock সমস্যা তখন ঘটে যখন দুই বা ততোধিক থ্রেড একে অপরের জন্য অপেক্ষা করে থাকে, যার ফলে কোনো থ্রেডই কাজ করতে পারে না। এটি সিস্টেমের কর্মক্ষমতাকে মারাত্মকভাবে কমিয়ে দেয়।

Deadlock রোধ করতে আপনি:

  • Locking Order নির্ধারণ করতে পারেন।
  • Timeout ব্যবহার করতে পারেন যাতে দীর্ঘ সময় ধরে লক আটকানো না থাকে।

TypeORM-এ Deadlock রোধে কিছু ব্যবস্থা নিতে পারেন, যেমন লক সময়সীমা নির্ধারণ করা।


সারাংশ

Concurrency Issues টাইপওআরএম ব্যবহারকারীদের জন্য একটি গুরুত্বপূর্ণ চ্যালেঞ্জ। এগুলো মোকাবেলার জন্য, TypeORM-এ Optimistic Locking, Pessimistic Locking, এবং Transactions ব্যবহৃত হয়। এই কৌশলগুলি ডেটাবেসের ডেটার অখণ্ডতা এবং সঠিকতা রক্ষা করে। Deadlock সমস্যার জন্য যথাযথ লকিং এবং টাইমআউট ব্যবস্থার মাধ্যমে আপনি ডেটাবেসের কর্মক্ষমতা উন্নত করতে পারেন। TypeORM-এ concurrency control কৌশলগুলি ব্যবহার করে আপনি আপনার অ্যাপ্লিকেশনের স্কেলেবিলিটি এবং পারফরম্যান্স উন্নত করতে পারবেন।

Content added By
Promotion

Are you sure to start over?

Loading...