一,先说一下为什么要分表

当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。

根据个人经验,mysql执行一个sql的过程如下:
1,接收到sql;2,把sql放到排队队列中 ;3,执行sql;4,返回执行结果。在这个执行过程中最花时间在什么地方呢?第一,是排队等待的时间,第二,sql的执行时间。其实这二个是一回事,等待的同时,肯定有sql在执行。所以我们要缩短sql的执行时间。

mysql中有一种机制是表锁定和行锁定,为什么要出现这种机制,是为了保证数据的完整性,我举个例子来说吧,如果有二个sql都要修改同一张表的同一条数据,这个时候怎么办呢,是不是二个sql都可以同时修改这条数据呢?很显然mysql对这种情况的处理是,一种是表锁定(myisam存储引擎),一个是行锁定(innodb存储引擎)。表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作。如果数据太多,一次执行的时间太长,等待的时间就越长,这也是我们为什么要分表的原因。

二,分表

1,做mysql集群,例如:利用mysql cluster ,mysql proxy,mysql replication,drdb等等

有人会问mysql集群,根分表有什么关系吗?虽然它不是实际意义上的分表,但是它启到了分表的作用,做集群的意义是什么呢?为一个数据库减轻负担,说白了就是减少sql排队队列中的sql的数量,举个例子:有10个sql请求,如果放在一个数据库服务器的排队队列中,他要等很长时间,如果把这10个sql请求,分配到5个数据库服务器的排队队列中,一个数据库服务器的队列中只有2个,这样等待时间是不是大大的缩短了呢?这已经很明显了。所以我把它列到了分表的范围以内,我做过一些mysql的集群:

linux mysql proxy 的安装,配置,以及读写分离

mysql replication 互为主从的安装及配置,以及数据同步

优点:扩展性好,没有多个分表后的复杂操作(php代码)

缺点:单个表的数据量还是没有变,一次操作所花的时间还是那么多,硬件开销大。

2,预先估计会出现大数据量并且访问频繁的表,将其分为若干个表

这种预估大差不差的,论坛里面发表帖子的表,时间长了这张表肯定很大,几十万,几百万都有可能。 聊天室里面信息表,几十个人在一起一聊一个晚上,时间长了,这张表的数据肯定很大。像这样的情况很多。所以这种能预估出来的大数据量表,我们就事先分出个N个表,这个N是多少,根据实际情况而定。以聊天信息表为例:

我事先建100个这样的表,message_00,message_01,message_02……….message_98,message_99.然后根据用户的ID来判断这个用户的聊天信息放到哪张表里面,你可以用hash的方式来获得,可以用求余的方式来获得,方法很多,各人想各人的吧。下面用hash的方法来获得表名:

<?php
function get_hash_table($table,$userid) {
$str = crc32($userid);
if($str<0){
$hash = “0”.substr(abs($str), 0, 1);
}else{
$hash = substr($str, 0, 2);
}

return $table.”_”.$hash;
}

echo get_hash_table(‘message’,’user18991′);     //结果为message_10
echo get_hash_table(‘message’,’user34523′);    //结果为message_13
?>

Read More →

想进行php的事务处理有下面几个步骤
1.关闭自动提交
2.开启事务处理
3.有异常就自动抛出异常提示再回滚
4.开启自动提交
下面是一个小示例利用pdo进行的php mysql事务处理,注意mysql只有这个InnoDB驱动是支持事务处理的,默认MyIsAM驱动不支持

<?php
   try{
       $pdo=new pdo(“mysql:host=localhost;dbname=xsphpdb”, “root”, “123456”, array(PDO::ATTR_AUTOCOMMIT=>0));//最后是关闭自动提交
       //$pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);//这个是通过设置属性方法进行关闭自动提交和上面的功能一样
       $pdo->setAttribute(PDO::ATTR_ERRMODE,  PDO::ERRMODE_EXCEPTION);//开启异常处理
   }catch(PDOException $e){
       echo “数据库连接失败:”.$e->getMessage();
       exit;
   }
   
   try{
       $pdo->beginTransaction();//开启事务处理       
       $price=500;
       $sql=”update zhanghao set price=price-{$price} where id=1″;
       $affected_rows=$pdo->exec($sql);
       if(!$affected_rows)
           throw new PDOException(“张三转出失败”);//那个错误抛出异常
       $sql=”update zhanghao set price=price+{$price} where id=3″;
       $affected_rows=$pdo->exec($sql);      
       if(!$affected_rows)
           throw new PDOException(“向李四转入失败”);
       echo “交易成功!”;
       $pdo->commit();//交易成功就提交
   }catch(PDOException $e){
       echo $e->getMessage();
       $pdo->rollback();
    
   $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);//自动提交,如果最后不自动提交,转账是不成功的  
   //设置错误报告模式 ERRMODE_SILENT    ERRMODE_WARNING

适配器是一种特殊的库,它有一个父类和任意数量的子类。子类可以访问其父类元素,但不能访问其兄弟类的元素。在你的控制器中,适配器为类库提供了一种优雅的语法,因此类库会就此获益甚至会需要分解成离散的类。

适配器的源文件存放在system/libraries 目录下, 命名一个和类名字相同的文件夹,文件夹下存放该类。同时在该文件夹中,有一个子文件夹叫做 drivers在其中包含了所有的子类。

要使用一个适配器,你需要在一个控制器里用如下的初始化函数初始它:

$this->load->driver(‘class name’);

这里的class name 是你想加载的适配器的名字。 比如说你想加载一个叫做”Some Parent”的适配器,你可以这样:

$this->load->driver(‘some_parent’);

适配器类中的方法可以用如下的方式来调用:

$this->some_parent->some_method();

这些作为子类的适配器能直接通过父类调用,而不用初始化。

$this->some_parent->child_one->some_method();
$this->some_parent->child_two->another_method();请查看缓存适配器的文件缓存使用方法

创建自己的适配器

适配器目录和文件结构布局的例子:

  • /application/libraries/Driver_name
    • Driver_name.php
    • drivers
      • Driver_name_subclass_1.php
      • Driver_name_subclass_2.php
      • Driver_name_subclass_3.php

注意: 为了在大小写敏感的文件系统上维持兼容性,这个 Driver_name 目录必须使用 ucfirst() 函数处理。

 

所有的类库文件存放在system/libraries 文件夹。大多数情况下你需要预先在controller中初始化后才能使用它们:

$this->load->library(‘class name’);

class name是你想要使用的类名。例如,要载入“表单验证类”,你可以这样做:

$this->load->library(‘form_validation’);

一旦类库被载入,你就可以按照用户手册中的方法来使用它们。

此外,多个类库可以通过传递包含类库的数组一次加载。

$this->load->library(array(’email’, ‘table’));

Read More →

辅助函数,顾名思义,是帮助我们完成特定任务的函数。每个辅助函数文件仅仅是一些函数的集合。例如,URL Helpers 可以帮助我们创建链接,Form Helpers 可以帮助我们创建表单,Text Helpers 提供一系列的格式化输出方式,Cookie Helpers 能帮助我们设置和读取COOKIE, File Helpers 能帮助我们处理文件,等等。

跟其他部分不同的是,辅助函数不是用类的方式来实现的。它们仅仅是一些简单的过程处理函数。 每个辅助函数处理一个特定的任务,并且不必依靠其他函数。

CodeIgniter 默认是没有载入辅助函数文件的,所以如果你想用辅助函数,就必须先载入它。 一旦被载入,辅助函数将全局可用(globally available),你可以在 controller 和 views 中使用它们。

辅助函数文件一般保存在 system/helpersapplication/helpers 文件夹中。CodeIgniter 将会先在 application/helpers 寻找对应的辅助函数文件, 如果目录不存在或者目录下没有对应的辅助函数文件,CI 才会载入 system/helpers 下的辅助函数文件。

Read More →