一個 MySQL 分庫分表php類
當一個表數據記錄過大時就會出現性能瓶頸,而一般對應的解決辦法是要么做分區表,要么分表,分區表就不說了,分表又分為垂直分割和水平分割,具體區 別請自行搜索。一般而言,分庫分表屬于水平分割,按照一定的規則將數據插入到不同的表中去。而分庫則可以很方便的轉移數據庫的壓力,比如將一個很大庫的分 別放在不同的服務器上。
下面是我寫的一個分庫分表的實現:
<?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>
本文由用戶 pc688 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!