PHP + MySQL लेनदेन उदाहरण


294

मुझे वास्तव में PHP फ़ाइल का सामान्य उदाहरण नहीं मिला है जहां MySQL लेनदेन का उपयोग किया जा रहा है। क्या आप मुझे इसका सरल उदाहरण दिखा सकते हैं?

और एक और सवाल। मैंने पहले ही बहुत प्रोग्रामिंग कर ली है और लेनदेन का उपयोग नहीं किया है। क्या मैं एक PHP फ़ंक्शन या कुछ भी रख सकता हूं 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");
Kirzilla

75
कृपया, mysql_*नए कोड में कार्यों का उपयोग न करें । वे अब बनाए नहीं हैं और आधिकारिक तौर पर पदावनत हैंलाल बॉक्स देखें? इसके बजाय तैयार किए गए कथनों के बारे में जानेंऔर PDO या MySQLi का उपयोग करें- यह लेख आपको यह तय करने में मदद करेगा कि कौन सा। यदि आप पीडीओ चुनते हैं, तो यहां एक अच्छा ट्यूटोरियल है
नफतली उर्फ ​​नील

6
क्या "mysql_query (" सेट AUTOCOMMIT = 0 ");" सभी फ़ंक्शन को प्रतिबद्ध फ़ंक्शन के लिए प्रतीक्षा करने के लिए सेट करें या यह केवल इसके संबंधित कनेक्शन के लिए है?
हामिद

1
@ नील, वास्तव में mysqlवंचित होने के बावजूद मर जाना, यह हमेशा के लिए PECL में उपलब्ध होगा।
पचेरियर

2
@Pacerier चीजें जो अपदस्थ हो जाती हैं, वे "मर" नहीं जाती हैं। वे विरासत सॉफ्टवेयर के लिए आधिकारिक तौर पर आयोजित किए जाते हैं, लेकिन नए सॉफ्टवेयर के लिए किसी भी अनुशंसित प्रथाओं से बनाए रखा और त्रस्त किया जा सकता है। तथ्य यह है कि, उपयोग न करेंmysql
taylorcressy

जवाबों:


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();
}


ध्यान दें कि, इस विचार के साथ, यदि कोई क्वेरी विफल होती है, तो अपवाद को फेंक दिया जाना चाहिए:

  • पीडीओ आप इसे कैसे कॉन्फ़िगर करते हैं, उसके आधार पर कर सकते हैं
  • कुछ अन्य API के साथ, आपको क्वेरी निष्पादित करने के लिए उपयोग किए गए फ़ंक्शन के परिणाम का परीक्षण करना पड़ सकता है, और खुद एक अपवाद फेंक सकते हैं।


दुर्भाग्य से, कोई जादू शामिल नहीं है। आप बस कहीं एक निर्देश नहीं डाल सकते हैं और लेन-देन स्वचालित रूप से किया जाता है: आपको अभी भी विशिष्ट होना चाहिए कि किस समूह के प्रश्नों को लेनदेन में निष्पादित किया जाना चाहिए।

उदाहरण के लिए, लेन-देन से पहले (begin अक्सर ) और लेन-देन के बाद प्रश्नों के एक जोड़े से पहले ( commitया तो )rollback ) और आप चाहते हैं उन प्रश्नों कोई फर्क नहीं पड़ता कि क्या हुआ निष्पादित (या नहीं) में सौदा।


35
सावधान रहें यदि आप ऐसे ऑपरेशन कर रहे हैं जो डीबी के अलावा अन्य अपवादों को फेंक सकते हैं। यदि ऐसा है, तो एक गैर-डीबी स्टेटमेंट से एक अपवाद अनजाने में रोलबैक हो सकता है (भले ही सभी डीबी कॉल सफल हों)। आम तौर पर, आपको लगता है कि वापस रोल करना एक अच्छा विचार है भले ही त्रुटि डीबी पक्ष में न हो, लेकिन कई बार 3 पार्टी / गैर-महत्वपूर्ण कोड हो सकते हैं, जिससे कोई महत्वपूर्ण अपवाद न हो, और आप अभी भी जारी रखना चाहते हैं सौदा।
१०:१०

6
यहाँ क्या $dbप्रकार है? mysqli?
जेक

3
@ जेक मेरा जवाब एक उदाहरण के लिए देखें जो mysqli (स्टाइल में पास्कल के दृष्टिकोण के समान) का उपयोग करता है।
इलेवनटाइने

2
PDOExceptionजरूरत पड़ने पर अपवादों को पकड़ने और यहां तक ​​कि जांच करने के लिए इसे आसानी से संशोधित किया जा सकता है । us2.php.net/PDOException
Yamiko

1
$ db पीडीओ ऑब्जेक्ट (कनेक्शन) है। रेफरी: php.net/manual/en/pdo.connections.php
Fil

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 सेट करने की कोई आवश्यकता नहीं है। लेनदेन हमेशा उसी तरह से काम करते हैं।
6

2
@ बबोंक - निश्चित नहीं कि यह InnoDB का मामला है?
बगेडकॉम

6
मुझे लगता है कि एक बार जब आप लेन-देन शुरू करते हैं तो यह कार्य करता है जैसे कि AUTOCOMMIT = 0
bgcode

4
@ बाबोंक सही है। एक बार जब कोई लेनदेन शुरू किया जाता है तो AUTOCOMMIT = 0 अनुमानित रूप से सेट किया जा रहा है और लेनदेन समाप्त होने या रोलबैक द्वारा समाप्त होने के बाद, MySql उस AUTOCOMMIT मान को वापस सेट करता है जिसका उपयोग लेनदेन शुरू करने से पहले किया गया था। नोट: आपको AUTOCOMMIT = 0 सेट नहीं करना चाहिए, क्योंकि परिवर्तनों को शुरू करने के बाद यदि आप दूसरी पंक्ति को सम्मिलित / अपडेट करने का निर्णय लेते हैं, तो आपको इसे स्पष्ट रूप से करना चाहिए।
इरोटीव

4
इंजन स्टोर होना चाहिए InnoDB, न कि MyISAM!
जावेद

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
StackOverflow पर आपका स्वागत है। कृपया अपने उत्तर के लिए हमेशा कुछ वर्णन पाठ लिखें।
एड्रियन हाइन

6
क्षमा करें im भिखारी, और मेरा बुरा अंग्रेजी, कोड की इसकी बहुत आसान परीक्षा - भिखारियों के लिए - प्रतिबद्ध () रोलबैक () शुरू () कक्षा DB में (उदाहरण के लिए), $ क्वेरी - एक बार नहीं - शायद $ क्वेरी 0 $ क्वेरी 1 - तब उन्हें
चोंच

20
उनकी टिप्पणियाँ उदाहरण को बहुत स्पष्ट करती हैं। अच्छा कोड पाठ का वर्णन करने की आवश्यकता नहीं होनी चाहिए। साथ ही प्रश्न एक सरल उदाहरण के लिए पूछता है। मुझे यह उत्तर पसंद है।
कोई नहीं

@GedzbergAlex एक ही प्रश्न के लिए लेन-देन की कोई आवश्यकता नहीं है, बस यह लेनदेन के बारे में भ्रमित करता है, क्या एक क्वेरी के लिए लेनदेन का उपयोग करने का कोई कारण है?
atı 14: ouɐɯ

35

चूंकि यह "php mysql लेनदेन" के लिए Google पर पहला परिणाम है, मैंने सोचा कि मैं एक उत्तर जोड़ूंगा जो स्पष्ट रूप से प्रदर्शित करता है कि यह mysqli के साथ कैसे किया जाए (जैसा कि मूल लेखक उदाहरण चाहते थे)। यहाँ PHP / mysqli के साथ लेनदेन का एक सरल उदाहरण है:

// 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   
}

इसके अलावा, ध्यान रखें कि PHP 5.5 में एक नया तरीका mysqli :: start_transaction है । हालाँकि, यह अभी तक PHP टीम द्वारा प्रलेखित नहीं किया गया है, और मैं अभी भी PHP 5.3 में अटका हुआ हूं, इसलिए मैं इस पर टिप्पणी नहीं कर सकता।


2
संबंधित नोट पर, मुझे अभी पता चला है कि यदि आप InnoDB तालिकाओं के साथ काम कर रहे हैं, तो लेन-देन के लिए ऑटोकॉमिट () दृष्टिकोण का उपयोग करते समय तालिकाओं को लॉक / अनलॉक करना संभव है, लेकिन start_transaction () दृष्टिकोण: MySQL
इलेवनटॉइन

वास्तविक mysqli कोड के साथ विस्तृत (और टिप्पणी की गई) उदाहरण के लिए +1। इसके लिए धन्यवाद। और वास्तव में लॉकिंग / लेनदेन के बारे में आपकी बात बहुत दिलचस्प है।
a.real.human.being

1
क्या "ऑटोकॉमिट (FALSE)" उसी डेटाबेस / टेबल में किसी अन्य कनेक्शन को प्रभावित करेगा? मेरा मतलब है कि अगर हम दो पृष्ठ खोलते हैं कि उनमें से एक ने "ऑटोकॉमिट (एफएएलएसई)" से अपना संबंध स्थापित किया है, लेकिन अन्य ने ऑटोकॉमिट फ़ंक्शन को छोड़ दिया है, क्या यह प्रतिबद्ध फ़ंक्शन की प्रतीक्षा करता है या नहीं। मैं जानना चाहता हूं कि क्या ऑटोकॉमिट कनेक्शन के लिए एक विशेषता है और डेटाबेस / टेबल के लिए नहीं। साभार
हामिद

2
@ हामिद $conn->autocommit(FALSE), उपरोक्त उदाहरण में, केवल व्यक्तिगत कनेक्शन को प्रभावित कर रहा है - इसका डेटाबेस के किसी भी अन्य कनेक्शन पर कोई प्रभाव नहीं है।
ग्यारहवें

1
नोट: इसके बजाय , यदि क्वेरी किसी मान्य परिणाम पर लौटने में सक्षम है जो गलत या शून्य का मूल्यांकन करने में सक्षम है, तो if (!result)करना चाहिए if (result === false)
टूलमेकरसेव

10

कृपया जांच लें कि आप कौन सा संग्रहण इंजन उपयोग कर रहे हैं। यदि यह MyISAM है, तो Transaction('COMMIT','ROLLBACK')समर्थित नहीं होगा क्योंकि केवल InnoDB भंडारण इंजन, MyISAM नहीं, लेनदेन का समर्थन करता है।


7

पीडीओ कनेक्शन का उपयोग करते समय:

$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/transactions/


सही कोड नहीं। trig_error सच लौटेगा (जब तक कि आपने अपना फोन खराब नहीं किया है), इसलिए $ परिणाम हमेशा सच होगा, इसलिए यह कोड किसी भी असफल क्वेरी को याद करेगा, और हमेशा प्रतिबद्ध रहने का प्रयास करेगा। समान रूप से परेशान होने पर, आप उपयोग करने के mysql_queryबजाय पुराने हटाए गए का उपयोग कर रहे हैं mysqli, भले ही आप उपयोग करने वाले ट्यूटोरियल से लिंक करते हैं mysqli। IMHO, आपको या तो इस बुरे उदाहरण को हटाना चाहिए, या इसे बदलने के लिए कोड का उपयोग करना चाहिए जैसा कि phpknowhow ट्यूटोरियल में लिखा गया है।
टूलमेकरस्टेव

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। कोई भी व्यक्ति इसमें रुचि रखता है जो क्लीनर उदाहरण के लिए कहीं और होना चाहिए।
टूलमेकरस्टेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.