Foeign Key Locking Transaction timeout when a second database connection is opened

℡╲_俬逩灬. 提交于 2019-12-23 20:26:52

问题


I'm having a problem involving a database transaction in one class that is timing out due to a secondary database connection being opened within the transaction; the problem started occurring when I added a foreign key constraint. And, testing using:

SET foreign_key_checks = 0;

I've been able to confirm this.

My database class looks like this (I've left off all of the methods):

class Db { 
function __construct($config) {
    $this->config = $config;
}

private function connect($config) {$dsn = 'mysql:host=' . $config['host'] . ';dbname=' . $config['dbname'] . ';charset=utf8';

$options = array(
            // PDO::ATTR_PERSISTENT => true,
            PDO::ATTR_EMULATE_PREPARES => false, 
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
           PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        );

$dbh = new PDO($dsn, $config['username'], $config['password'], $options);
$dbh->exec("SET NAMES utf8;"); 

return $dbh;
 }      
}

My model looks like this:

class Model {

    function __construct() {
        $this->db = new Db(array('host'=>DB_HOST,'dbname'=>DB_NAME,'username'=>DB_USERNAME,'password'=>DB_PASSWORD));
    }

}

The code below then performs a little bit of logic, then an insert into the question_orders table: question_orders has a column question_id, with a foreign key index, which references the parent table questions; I think that the problem is that Assessment_Question_Orders extends the Model and creates a new database connection? Any thoughts on how to maintain both the transaction and foreign key aspects would be appreciated.

  class This_Is_A_Problem extends Model() {

       public function __construct() {
             parent::construct();
           }

       public function problemFunction()  {

    /*variable init code left out*/

    $this->db->beginTransaction();
    $db_result = false;
    try {

    $db_result = $this->db->insert('questions', $questions_data);
    $new_insert_id = $this->db->lastInsertId();

    $assessment_question_orders = new Assessment_Question_Orders();

 $question_number = $assessment_question_orders->insertSingleQuestionOrder($module_id, $new_insert_id);

    $db_result = $this->db->commit();

    }
    } catch (PDOException $e) {

     $this->db->rollBack();

    }}}

回答1:


One thread should (usually) have only one connection to the database. So I recommend one of these patterns:

Plan A: a single $db passed into all classes:

$db = new PDO(...);
$my_obj = new My_Class($db);  -- $db is saved in $this->db for use within the methods of My_Class.

Plan B: a singleton Db class with a getter method:

// Singleton (of sorts)
class Db
{
    private static $db;
    function __construct()
    {
        self::$db = new PDO(...);
        // A variant would include "lazy" instantiation of self::$Db. 
    }
    function Get_Db()  { return self::$db; } // All calls get the same `db`
}
class My_class
{
    function My_Method()
    {
        $db = Db::Get_Db();
        $db->...
    }
}

new Db();   // one time call at start of program

There is only rarely a need to have two db connections in a single program. Plan A easily allows for such. (But see if you can avoid it -- you are in trouble now because of it.)



来源:https://stackoverflow.com/questions/31089317/foeign-key-locking-transaction-timeout-when-a-second-database-connection-is-open

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!