一個 MySQL 分庫分表php類

pc688 9年前發布 | 2K 次閱讀 PHP MySQL

當一個表數據記錄過大時就會出現性能瓶頸,而一般對應的解決辦法是要么做分區表,要么分表,分區表就不說了,分表又分為垂直分割和水平分割,具體區 別請自行搜索。一般而言,分庫分表屬于水平分割,按照一定的規則將數據插入到不同的表中去。而分庫則可以很方便的轉移數據庫的壓力,比如將一個很大庫的分 別放在不同的服務器上。

下面是我寫的一個分庫分表的實現:

    <?php
/**

 * User: guoyu 
 * Date: 14-8-12 
 * Time: 下午3:16 
 */  

namespace App\Model\Database;  

class Config  
{  
    public $dsn;  
    public $user;  
    public $password;  
    /** 
     * @var string 分庫分表后得到的數據庫名 
     */  
    public $dbname;  
    /** 
     * @var string 分庫分表后得到的表名 
     */  
    public $table;  

    /** 
     * @var array MySQL 配置數組 
     */  
    private static $config;  

    /** 
     * @var string 配置文件路徑 
     */  
    private static $configFile = 'mysql.php';  

    public function __construct($dbname, $table, $id = 0)  
    {  
        if (is_null(static::$config)) {  
            $config = include(static::$configFile);  
            static::$config = $config;  
        }  

        $config = static::$config;  
        if (isset($config['shared']) && isset($config['shared'][$dbname])) {  
            $dbconfig = $config['shared'][$dbname];  
            $id = is_numeric($id) ? (int)$id : crc32($id);  
            $database_id = ($id / $dbconfig['database_split'][0]) % $dbconfig['database_split'][1];  
            $table_id = ($id / $dbconfig['table_split'][0]) % $dbconfig['table_split'][1];  

            foreach ($dbconfig['host'] as $key => $conf) {  
                list($from, $to) = explode('-', $key);  
                if ($from <= $database_id && $database_id <= $to) {  
                    $the_config = $conf;  
                }  
            }  

            $this->dbname = $dbname . '_' . $database_id;  
            $this->table = $table . '_' . $table_id;  
        } else {  
            $this->dbname = $dbname;  
            $this->table = $table;  
            $the_config = $config['db'][$dbname];  
        }  
        $c = $the_config;  
        if (isset($c['unix_socket']) && $c['unix_socket']) {  
            $this->dsn = sprintf('mysql:dbname=%s;unix_socket=%s', $this->dbname, $c['unix_socket']);  
        } else {  
            $this->dsn = sprintf('mysql:dbname=%s;host=%s;port=%s', $this->dbname, $c['host'], $c['port']);  
        }  
        $this->user = $c['user'];  
        $this->password = $c['password'];  
    }  

}  


Config 類就做一個事情,根據配置文件,去拿到對應的庫和表的鏈接配置,然后客戶可以根據 dsn 去鏈接對應的數據庫。對應的配置文件如下:

[php] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片

<?php  
/** 
 * User: guoyu 
 * Date: 14-8-6 
 * Time: 上午11:19 
 */  

$default = array(  
    'unix_socket' => null,  
    'host' => 'localhost',  
    'port' => '3306',  
    'user' => 'root',  
    'password' => '',  
);  

$config = array(  
    // 不進行分庫分表的數據庫  
    'db' => array(  
        'my_site' => $default,  
    ),  
    // 分庫分表  
    'shared' => array(  
        'user' => array(  
            'host' => array(  
                /** 
                 * 編號為 0 到 10 的庫使用的鏈接配置 
                 */  
                '0-10' => $default,  
                /** 
                 * 編號為 11 到 28 的庫使用的鏈接配置 
                 */  
                '11-28' => $default,  
                /** 
                 * 編號為 29 到 99 的庫使用的鏈接配置 
                 */  
                '29-99' => $default,  

            ),  

            // 分庫分表規則  
            /** 
             * 下面的配置對應百庫百表 
             * 如果根據 uid 進行分表,假設 uid 為 543234678,對應的庫表為: 
             *  (543234678 / 1) % 100 = 78 為編號為 78 的庫 
             *  (543234678 / 100) % 100 = 46 為編號為 46 的表 
             */  
            'database_split' => array(1, 100),  
            'table_split' => array(100, 100),  
        ),  
    ),  
);  


return $config;  


給出一個使用這個分庫分表的例子:

[php] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片

<?php  
/** 
 * User: guoyu 
 * Date: 14-8-6 
 * Time: 上午10:23 
 */  

namespace App\Model;  

use App\Model\Database\Config;  
use \PDO;  

abstract class Model  
{  
    /** 
     * @var Config 
     */  
    public $config;  

    /** 
     * @var PDO 
     */  
    public $connection;  

    protected $dbnamePrefix;  
    protected $tablePrefix;  

    /** 
     * @var string 分庫分表后對應的表 
     */  
    protected $table;  

    public function __construct($id)  
    {  
        $this->config = new Config($this->dbnamePrefix, $this->tablePrefix, $id);  
        $this->connection = new Pdo($this->config->dsn, $this->config->user, $this->config->password);  
        $this->table = $this->config->table;  
    }  

    public function update(array $data, array $where = array())  
    {  

    }  

    public function select(array $where)  
    {  

    }  

    public function insert(array $data)  
    {  

    }  

    public function query($sql)  
    {  
        return $this->connection->query($sql);  
    }  
}  </pre> 


下面這個例子展示了如何使用上述的 Model 類:

    <?php
/**

 * User: guoyu 
 * Date: 14-8-12 
 * Time: 下午4:06 
 */  

require 'Config.php';  
require 'Model.php';  

use App\Model\Model;  

class User extends Model  
{  
    protected $dbnamePrefix = 'user';  
    protected $tablePrefix = 'userinfo';  
}  

$user = new User(4455345345);  

print_r($user);  </pre> 


來自:http://blog.csdn.net/phpfenghuo/article/details/45342311

 本文由用戶 pc688 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!