পিএইচপি + মাইএসকিউএল লেনদেনের উদাহরণ


294

মাইএসকিউএল লেনদেন ব্যবহৃত হচ্ছে এমন পিএইচপি ফাইলের সাধারণ উদাহরণ আমি সত্যিই খুঁজে পাইনি। আপনি কি আমাকে এর সহজ উদাহরণ দেখাতে পারেন?

এবং আরও একটি প্রশ্ন। আমি ইতিমধ্যে প্রচুর প্রোগ্রামিং করেছি এবং লেনদেন ব্যবহার করিনি। আমি কি কোনও পিএইচপি ফাংশন বা এমন কিছু রাখতে header.phpপারি যদি কেউ mysql_queryব্যর্থ হয় তবে অন্যরাও ব্যর্থ হয়?


আমি মনে করি আমি এটি বের করেছি, এটা কি ঠিক ?:

mysql_query("SET AUTOCOMMIT=0");
mysql_query("START TRANSACTION");

$a1 = mysql_query("INSERT INTO rarara (l_id) VALUES('1')");
$a2 = mysql_query("INSERT INTO rarara (l_id) VALUES('2')");

if ($a1 and $a2) {
    mysql_query("COMMIT");
} else {        
    mysql_query("ROLLBACK");
}

10
আপনি mysql_query("BEGIN");ক্রমের পরিবর্তে ব্যবহার করতে পারেনmysql_query("SET AUTOCOMMIT=0"); mysql_query("START TRANSACTION");
কিরজিলা

75
দয়া করে mysql_*নতুন কোডে ফাংশন ব্যবহার করবেন না । এগুলি আর রক্ষণাবেক্ষণ করা হয় না এবং সরকারীভাবে হ্রাস করা হয় । দেখুন লাল বক্স ? পরিবর্তে প্রস্তুত বিবৃতি সম্পর্কে জানুন, এবং PDO বা মাইএসকিউএলি ব্যবহার করুন- এই নিবন্ধটি আপনাকে সিদ্ধান্ত নিতে সহায়তা করবে। আপনি যদি PDO চয়ন করেন তবে এখানে একটি ভাল টিউটোরিয়াল রয়েছে
নফতালি ওরফে নীল

6
"Mysql_query (" SET AUTOCOMMIT = 0 ") কি করে?" প্রতিশ্রুতিবদ্ধ ক্রিয়াকলাপের জন্য অপেক্ষা করার জন্য সমস্ত সংযোগ সেট করে নাকি এটি কেবল এর সম্পর্কিত সংযোগের জন্য?
হামিদ

1
@ নিল, প্রকৃতপক্ষে অবজ্ঞাপূর্ণ mysqlহওয়া সত্ত্বেও মারা যায়, এটি পিসিএলে চিরকালের জন্য উপলব্ধ থাকবে।
পেসারিয়ার

2
@ পেসারিয়ার যে জিনিসগুলি হ্রাস পেয়েছে সেগুলি "মরে" না। এগুলি আনুষ্ঠানিকভাবে লিগ্যাসি সফ্টওয়্যারের জন্য রাখা হয় তবে নতুন সফ্টওয়্যার সম্পর্কিত কোনও প্রস্তাবিত অনুশীলন থেকে বজায় রাখা এবং আটকা দেওয়া বন্ধ করে দেয়। সত্যটি রয়ে গেছে, ব্যবহার করবেন নাmysql
টেলরক্র্যাসি

উত্তর:


325

লেনদেনের সাথে কাজ করার সময় আমি যে ধারণাটি ব্যবহার করি তা এ জাতীয় দেখায় (আধা ছদ্ম কোড) :

try {
    // First of all, let's begin a transaction
    $db->beginTransaction();

    // A set of queries; if one fails, an exception should be thrown
    $db->query('first query');
    $db->query('second query');
    $db->query('third query');

    // If we arrive here, it means that no exception was thrown
    // i.e. no query has failed, and we can commit the transaction
    $db->commit();
} catch (Exception $e) {
    // An exception has been thrown
    // We must rollback the transaction
    $db->rollback();
}


দ্রষ্টব্য, এই ধারণার সাথে যদি কোনও প্রশ্ন ব্যর্থ হয় তবে একটি ব্যতিক্রম অবশ্যই ছুঁড়ে দেওয়া উচিত:

  • আপনি কীভাবে এটি কনফিগার করবেন তার উপর নির্ভর করে PDO এটি করতে পারে
    • দেখা PDO::setAttribute
    • এবং PDO::ATTR_ERRMODEএবংPDO::ERRMODE_EXCEPTION
  • অন্যথায়, অন্য কোনও এপিআইয়ের সাথে, আপনাকে কোয়েরি চালাতে ব্যবহৃত ফাংশনের ফলাফলটি পরীক্ষা করতে হতে পারে এবং নিজেই একটি ব্যতিক্রম নিক্ষেপ করতে পারে।


দুর্ভাগ্যক্রমে, কোন জাদু জড়িত নেই। আপনি কোথাও কোনও নির্দেশনা রাখতে পারেন এবং লেনদেন স্বয়ংক্রিয়ভাবে সম্পন্ন করতে পারবেন না: কোনও লেনদেনের ক্ষেত্রে কোন গ্রুপের কোয়েরিগুলি নির্বাহ করতে হবে তা আপনাকে এখনও নির্দিষ্ট করতে হবে।

উদাহরণ হিসেবে বলা যায়, বেশ ঘন ঘন আপনি লেনদেনের আগে প্রশ্নের একটি দম্পতি আছে করব (আগে begin) এবং লেনদেনের পর প্রশ্নের আরেকটি দম্পতি (পরে পারেন commitবা rollback) এবং আপনার চাইবেন সেই প্রশ্নের কোন ব্যাপার কি ঘটেছে মৃত্যুদন্ড কার্যকর (অথবা না) মধ্যে লেনদেন.


35
আপনি যদি এমন অপারেশন করছেন যা ডিবি ব্যতীত অন্য কোনও ব্যতিক্রম ছুঁড়ে ফেলতে পারে তবে সাবধান হন। যদি তা হয় তবে নন-ডিবি বিবৃতি থেকে একটি ব্যতিক্রম অজান্তেই রোলব্যাকের কারণ হতে পারে (এমনকি সমস্ত ডিবি কল সফল হলেও)। সাধারণত, আপনি ভাবেন যে পিছন ফিরে ঘুরিয়ে দেওয়া একটি ভাল ধারণা তবুও ত্রুটিটি ডিবি দিকে না থাকলেও তৃতীয় পক্ষের / অ-সমালোচনামূলক কোডটি অত-গুরুত্বপূর্ণ-তেমন ব্যতিক্রমগুলির কারণ হতে পারে এবং আপনি এখনও অবিরত রাখতে চান লেনদেন.
হালিল üzgür

6
$dbএখানে টাইপ কি ? mysqli?
জেক

3
@ জ্যাক আমার উত্তরটি এমন উদাহরণের জন্য দেখুন যা মাইসকিলি ব্যবহার করে (পাস্কেলের পদ্ধতির মতো শৈলীতে)।
এলেগারটিও

2
এটি প্রয়োজনে সহজেই PDOExceptionব্যতিক্রমের মানগুলি ধরা ও পরীক্ষা করতে সংশোধন করা যেতে পারে । us2.php.net/PDOException
ইয়ামিকো

1
b db হ'ল PDO অবজেক্ট (সংযোগ)। সূত্র: php.net/manual/en/pdo.connections.php
ফীল

110

আমি মনে করি আমি এটি বের করেছি, এটা কি ঠিক ?:

mysql_query("START TRANSACTION");

$a1 = mysql_query("INSERT INTO rarara (l_id) VALUES('1')");
$a2 = mysql_query("INSERT INTO rarara (l_id) VALUES('2')");

if ($a1 and $a2) {
    mysql_query("COMMIT");
} else {        
    mysql_query("ROLLBACK");
}

26
অটোকোমিট = 0 সেট করার দরকার নেই। লেনদেন সর্বদা সেইভাবে কাজ করে।
বিজিকোড

2
@ বাবোনক - নিশ্চিত নয় যে এটি ইনোডিবি-র ক্ষেত্রে?
বাগডকম

6
আমি মনে করি আপনি একবার লেনদেন শুরু করলে এটি কাজ করে যেমন AUTOCOMMIT = 0
বিজিকোড

4
@ বাবঙ্ক ঠিক বলেছেন একবার কোনও লেনদেন শুরু হয়ে গেলে আউটকোমিট = 0 সুস্পষ্টভাবে সেট করা হয় এবং লেনদেন হয় কমিট বা রোলব্যাকের মাধ্যমে শেষ হওয়ার পরে, মাইএসকিএল লেনদেন শুরুর আগে ব্যবহৃত অটোকোমিট মানটি সেট করে। দ্রষ্টব্য: আপনার অটোকোমিট = 0 সেট করা উচিত নয়, কারণ পরিবর্তনগুলি করার পরে যদি আপনি অন্য সারি সন্নিবেশ / আপডেট করার সিদ্ধান্ত নেন তবে আপনি এটি স্পষ্টভাবে প্রতিশ্রুতিবদ্ধ হওয়া উচিত।
এরোটেভ

4
ইঞ্জিন স্টোরটি ইনোডিবি হওয়া উচিত, মাইআইএসএএম নয়!
জাভাদ

39
<?php

// trans.php
function begin(){
    mysql_query("BEGIN");
}

function commit(){
    mysql_query("COMMIT");
}

function rollback(){
    mysql_query("ROLLBACK");
}

mysql_connect("localhost","Dude1", "SuperSecret") or die(mysql_error());

mysql_select_db("bedrock") or die(mysql_error());

$query = "INSERT INTO employee (ssn,name,phone) values ('123-45-6789','Matt','1-800-555-1212')";

begin(); // transaction begins

$result = mysql_query($query);

if(!$result){
    rollback(); // transaction rolls back
    echo "transaction rolled back";
    exit;
}else{
    commit(); // transaction is committed
    echo "Database transaction was successful";
}

?>

এর মতো একটি বিস্তৃত এবং উচ্চ প্রোফাইল প্রশ্নের জন্য, উত্তরগুলিও যদি এটি প্রতিফলিত করে তবে দুর্দান্ত হবে। আপনার কোডের নমুনা দুর্দান্ত তবে আপনি কি আরও বিস্তারিত বলতে পারবেন? লেনদেন সম্পর্কে ব্যাখ্যা কর, কেন, কখন এবং কোথায়? শেষ পর্যন্ত, আপনার ব্যাখ্যার সাথে কোডটি লিঙ্ক করুন।
ডেনিস হারবারিক

3
স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম। দয়া করে সর্বদা আপনার উত্তরে কিছু বর্ণনামূলক পাঠ্য লিখুন।
অ্যাড্রিয়ান হাইন

6
দুঃখিত আমি বেগুনী, এবং আমার খারাপ ইংরেজি, কোডটির খুব সহজ পরীক্ষা - ভিক্ষুকদের জন্য - কমিট () রোলব্যাক () শুরু () ডিবি ক্লাসে রেখেছেন (উদাহরণস্বরূপ), $ কোয়েরি - একবার নয় - সম্ভবত $ ক্যোয়ারী 0 $ ক্যুয়ার 1 - তারপরে তাদের চেক করুন - আমি এই কোডটি ব্যবহার করি, এটি বোঝা খুব সহজ =)
গেডজবার্গ অ্যালেক্স

20
তাঁর মন্তব্য উদাহরণটি বেশ স্পষ্ট করে তোলে। ভাল কোডটির পাঠ্য বর্ণনার দরকার নেই। এছাড়াও প্রশ্নটি একটি সাধারণ উদাহরণ জিজ্ঞাসা করে। আমি এই উত্তর পছন্দ।
কোনটি

@ গেডজবার্গএলক্স একটি একক প্রশ্নের জন্য লেনদেনের প্রয়োজন নেই, কেবল এটি লেনদেন সম্পর্কে বিভ্রান্ত হয়, একক কোয়েরির জন্য লেনদেনকে ব্যবহার করার কোনও কারণ আছে কি?
ʞɔıɥʇɹɐʞ ɐɯ

35

যেহেতু "পিএইচপি মাইএসকিএল লেনদেন" এর জন্য গুগলে এটি প্রথম ফলাফল, আমি ভেবেছিলাম যে আমি এমন একটি উত্তর যুক্ত করব যা স্পষ্টভাবে প্রদর্শিত হবে যে কীভাবে এটি মাইসকিলি দিয়ে করবেন (মূল লেখক যেমন উদাহরণ চেয়েছিলেন)। এখানে পিএইচপি / মাইসকলি দিয়ে লেনদেনের সরল উদাহরণ রয়েছে:

// let's pretend that a user wants to create a new "group". we will do so
// while at the same time creating a "membership" for the group which
// consists solely of the user themselves (at first). accordingly, the group
// and membership records should be created together, or not at all.
// this sounds like a job for: TRANSACTIONS! (*cue music*)

$group_name = "The Thursday Thumpers";
$member_name = "EleventyOne";
$conn = new mysqli($db_host,$db_user,$db_passwd,$db_name); // error-check this

// note: this is meant for InnoDB tables. won't work with MyISAM tables.

try {

    $conn->autocommit(FALSE); // i.e., start transaction

    // assume that the TABLE groups has an auto_increment id field
    $query = "INSERT INTO groups (name) ";
    $query .= "VALUES ('$group_name')";
    $result = $conn->query($query);
    if ( !$result ) {
        $result->free();
        throw new Exception($conn->error);
    }

    $group_id = $conn->insert_id; // last auto_inc id from *this* connection

    $query = "INSERT INTO group_membership (group_id,name) ";
    $query .= "VALUES ('$group_id','$member_name')";
    $result = $conn->query($query);
    if ( !$result ) {
        $result->free();
        throw new Exception($conn->error);
    }

    // our SQL queries have been successful. commit them
    // and go back to non-transaction mode.

    $conn->commit();
    $conn->autocommit(TRUE); // i.e., end transaction
}
catch ( Exception $e ) {

    // before rolling back the transaction, you'd want
    // to make sure that the exception was db-related
    $conn->rollback(); 
    $conn->autocommit(TRUE); // i.e., end transaction   
}

এছাড়াও, মনে রাখবেন যে পিএইচপি 5.5 এর একটি নতুন পদ্ধতি mysqli :: start_transaction রয়েছে । যাইহোক, এটি পিএইচপি টিম দ্বারা এখনও নথিভুক্ত করা হয়নি, এবং আমি এখনও পিএইচপি 5.3 এ আটকেছি, তাই আমি এটি সম্পর্কে মন্তব্য করতে পারি না।


2
সম্পর্কিত নোটটিতে, আমি কেবল আবিষ্কার করেছি যে আপনি যদি InnoDB টেবিলগুলির সাথে কাজ করছেন তবে লেনদেনের জন্য স্বতঃকমিত্ট () পদ্ধতির ব্যবহার করার সময় টেবিলগুলি লক / আনলক করা সম্ভব, তবে আর্টিং-ট্রান্সজেকশন () পদ্ধতির ব্যবহার করার সময় এটি সম্ভব নয়: মাইএসকিউএল ডকুমেন্টেশন
এলেগারটিও

প্রকৃত mysqli কোড সহ বিস্তারিত (এবং মন্তব্য করা) উদাহরণের জন্য +1। এর জন্য ধন্যবাদ. এবং লকিং / লেনদেন সম্পর্কে আপনার বক্তব্য সত্যই আকর্ষণীয়।
a.real.human.being

1
"অটোোকমিট (ফলস)" একই ডাটাবেস / সারণীতে অন্য সংযোগে প্রভাব ফেলবে? আমার অর্থ যদি আমরা দুটি পৃষ্ঠাগুলি খুলি যেগুলির মধ্যে একটি তার "সংযোজন (FALSE)" এর সাথে সংযোগ স্থাপন করেছে তবে অন্য একটি স্বতঃসংশোধন ফাংশন ছেড়ে দিয়েছে, এটি কি প্রতিশ্রুতিবদ্ধ ফাংশনের জন্য অপেক্ষা করে না। আমি জানতে চাই যে অটোকমিটটি সংযোগগুলির জন্য কোনও বৈশিষ্ট্য, ডাটাবেস / সারণীর জন্য নয়। ধন্যবাদ
হামিদ

2
$conn->autocommit(FALSE)উপরের উদাহরণে হামিদ কেবল পৃথক সংযোগকেই প্রভাবিত করছে - এটি ডাটাবেসের সাথে অন্য কোনও সংযোগে প্রভাব ফেলবে না।
একাদশ

1
দ্রষ্টব্য: পরিবর্তে if (!result), করা উচিত if (result === false), যদি কোয়েরিটি কোনও কার্যকর ফলাফল ফেরত দিতে সক্ষম হয় যা ভুয়া বা শূন্যকে মূল্যায়ন করবে।
টুলমেকারস্টেভ

10

আপনি কোন স্টোরেজ ইঞ্জিন ব্যবহার করছেন তা পরীক্ষা করে দেখুন। যদি এটি মাইআইএসএএম হয়, তবে Transaction('COMMIT','ROLLBACK')সমর্থন করা হবে না কারণ কেবল ইনোডিবি স্টোরেজ ইঞ্জিন, মাইআইএসএএম নয়, লেনদেনকে সমর্থন করে।


7

PDO সংযোগ ব্যবহার করার সময়:

$pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8', $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // this is important
]);

আমি প্রায়শই লেনদেন পরিচালনার জন্য নিম্নলিখিত কোড ব্যবহার করি:

function transaction(Closure $callback)
{
    global $pdo; // let's assume our PDO connection is in a global var

    // start the transaction outside of the try block, because
    // you don't want to rollback a transaction that failed to start
    $pdo->beginTransaction(); 
    try
    {
        $callback();
        $pdo->commit(); 
    }
    catch (Exception $e) // it's better to replace this with Throwable on PHP 7+
    {
        $pdo->rollBack();
        throw $e; // we still have to complain about the exception
    }
}

ব্যবহারের উদাহরণ:

transaction(function()
{
    global $pdo;

    $pdo->query('first query');
    $pdo->query('second query');
    $pdo->query('third query');
});

এইভাবে লেনদেন-পরিচালন কোডটি প্রকল্প জুড়ে সদৃশ হয় না। যা একটি ভাল জিনিস, কারণ, এই থ্রেডে অন্যান্য পিডিও-বর্ধিত উত্তরগুলি থেকে বিচার করা, এতে ভুল করা সহজ। অতি সাধারণ ব্যতিক্রমগুলি পুনর্বিবেচনা করতে এবং tryব্লকের ভিতরে লেনদেন শুরু করতে ভুলে যাচ্ছেন ।


5

আমি অনুসন্ধানগুলির ভেক্টর পেতে এবং একটি লেনদেন করার জন্য একটি ফাংশন করেছি, সম্ভবত কেউ এটি দরকারী খুঁজে পেতে পারেন:

function transaction ($con, $Q){
        mysqli_query($con, "START TRANSACTION");

        for ($i = 0; $i < count ($Q); $i++){
            if (!mysqli_query ($con, $Q[$i])){
                echo 'Error! Info: <' . mysqli_error ($con) . '> Query: <' . $Q[$i] . '>';
                break;
            }   
        }

        if ($i == count ($Q)){
            mysqli_query($con, "COMMIT");
            return 1;
        }
        else {
            mysqli_query($con, "ROLLBACK");
            return 0;
        }
    }

3

আমার এটি ছিল, তবে নিশ্চিত না যে এটি সঠিক কিনা। এটিও চেষ্টা করে দেখতে পারেন।

mysql_query("START TRANSACTION");
$flag = true;
$query = "INSERT INTO testing (myid) VALUES ('test')";

$query2 = "INSERT INTO testing2 (myid2) VALUES ('test2')";

$result = mysql_query($query) or trigger_error(mysql_error(), E_USER_ERROR);
if (!$result) {
$flag = false;
}

$result = mysql_query($query2) or trigger_error(mysql_error(), E_USER_ERROR);
if (!$result) {
$flag = false;
}

if ($flag) {
mysql_query("COMMIT");
} else {        
mysql_query("ROLLBACK");
}

আইডিয়া এখান থেকে: http://www.phpknowhow.com/mysql/transferences/


সঠিক কোড নয়। ট্রিগার_অরার সত্য ফিরে আসবে (যদি না আপনি নিজের কলটি সরিয়ে ফেলে) তবে ফলাফলটি সর্বদা সত্য হবে, সুতরাং এই কোডটি কোনও ব্যর্থ কোয়েরি মিস করবে এবং সর্বদা প্রতিশ্রুতিবদ্ধ হওয়ার চেষ্টা করবে। একইভাবে উদ্বেগজনক, আপনি যে টিউটোরিয়াল ব্যবহার করছেন তার সাথে লিঙ্ক দিলেও আপনি mysql_queryব্যবহারের পরিবর্তে পুরানো অবচয় mysqliব্যবহার করছেন mysqli। আইএমএইচও, আপনার এই খারাপ উদাহরণটি মুছে ফেলা উচিত, বা phpজ্ঞাহ্য টিউটোরিয়ালে লিখিত কোড ব্যবহারের জন্য এটি প্রতিস্থাপন করা উচিত।
টুলমেকারস্টেভ

2

mysqli_multi_queryঅনুমান সহ আরও একটি পদ্ধতিগত শৈলীর উদাহরণ , ধরে নেওয়া $queryহয় সেমিকোলন-বিচ্ছিন্ন বিবৃতিতে পূর্ণ।

mysqli_begin_transaction ($link);

for (mysqli_multi_query ($link, $query);
    mysqli_more_results ($link);
    mysqli_next_result ($link) );

! mysqli_errno ($link) ?
    mysqli_commit ($link) : mysqli_rollback ($link);

1
কিছুটা অদ্ভুত কোড তবে অন্তত এটি ব্যবহারের পরামর্শ দেয় mysqli_multi_query। এতে আগ্রহী যে কোনও ব্যক্তির ক্লিনার উদাহরণের জন্য গুগল করা উচিত।
টুলমেকারস্টেভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.