SQL Relay

你是不是也在寻找LAMP结构下的PHP连接池?如果没找到更好的,建议你试试SQL Relay.
之前我曾将写过一篇关于SQL Relay的blog,介绍了一下怎么把SQL Realy用在PEAR DB中。事实证明,这样使用并不能有效的缓解MySQL中产生大量连接的问题,因为PHP从SQL Relay得到的还是一个真实的数据库连接,也就是说PHP连接一次,SQL Relay就要提供一个,至于这个连接什么时候还给SQL Relay,还是PHP说了算,SQL Relay没有管理权,所以运行了一段时间之后SQL Relay就会一下子增加N个连接,然后崩溃。。。。。。希望你没碰到这种状况。
最近实验了一下用另外一种方式使用SQL Relay,首先建立一个SQL Relay服务器,直接连接数据库,然后PHP端只建立到SQL Relay服务器的TCP连接,并不参与对数据库连接的使用和管理,基本的原理就是PHP连接到SQL Relay服务器,传递要运行的SQL语句,SQL Relay负责把语句通过一个空闲的连接送到MySQL服务器去执行得到结果后立即断开,然后返回给PHP,这样大量的PHP请求传递给SQL Relay,后者负责去维护一个MySQL连接池,完全拥有对数据库连接的管理权。经过实验,效果比较理想。
安装和配置运行这里就不赘述了,有问题可以mail我,说一下怎么实现PHP到SQL Relay的连接。
安装成功之后,在php.ini里设置sqlrelay.so的extension信息,然后可以按照下面的方法写一个class,你可以按照getRow方法的样子去实现其他的查询方法。

class SQLR_DB
{
private $conn;
private $cur;
private function __contruct(){}//构造函数
private function _conn($server,$port,$user,$password,$retrytime,$tries)//建立连接的私有方法(server:SQL Relay的服务器
,port:端口,user:用户名,password:密码,retrytime:隔多长时间重新连接,tries:重新连接的次数)
{
$this -> conn = sqlrcon_alloc($server,$port,"",$user,$password,$retrytime,$tries);
$this -> cur = sqlrcur_alloc($this->conn);
}

private function retrieve($sql) //传递SQL语句到SQL Relay服务器,获得返回结果的方法
{
if( !$sql) return false;
$this -> _conn("server" , "port" , "user" , "password" , "retrytime", "tries"); if(!sqlrcur_sendQuery($this->cur,$sql))
{
echo sqlrcur_errorMessage($this->cur);
sqlrcur_free($this->cur); sqlrcon_free($this->conn);
return null; }
//sqlrcon_endSession($con); for($i=0; $i < sqlrcur_rowCount($this->cur); $i++)
{ $res[] = sqlrcur_getRowAssoc($this->cur,$i);
} sqlrcur_free($this->cur);
sqlrcon_free($this->conn); return $res; }


然后在数据层通过这个class来取得数据。例如:

function getOneRecord($sql)
{
if(!$sql) return false;
$sdb = new SQLR_DB();
return $sdb -> getRow($sql);
}
public function getRow($sql)//取一行的共有方法
{
if(!$sql) return false;
$res = $this -> retrieve($sql);
if("null" == $res) return null;
return $res[0];
}
}

现在的问题是,用这种方法来对付所有的读操作是可以的(用来管理所有的对Slave服务器的读操作),但是用来管理写操作的时候却遇到了问题,在向数据库中写入一条记录,并返回插入ID的时候,以前可以使用mysql_insert_id方法,可是用SQL Relay来管理数据库连接之后,每次查询都有可能使用不同的连接,因此执行完一条insert语句,再去执行mysql_insert_id的时候,使用的很可能已经不是之前的连接了,因此也就不能返回正确的结果。不知道有哪位大侠知道解决方法的,请不吝赐教,在下感激不尽:)

谨慎使用php的ip2long函数

把ip数据保存在数据库(MySQL)中时候,我们习惯用ip2long函数生成整型,然后存放在一个int(11)类型的字段中,但是,在不同的系统平台上,ip2long函数得到的值是不同的,因此可能造成在从数据库中读出数据,用long2ip得到ip的时候产生错误,说一下我们碰到的情况:
我们用一个int(11)类型(范围-2147483648 - 2147483647)来保存把一个ip地址用ip2long处理得到的结果,例如ip是’202.105.77.179′,那么在32位机器上得到的结果是:-899068493,而在64位机器上却得到3395898803.然后把它写入数据库,由于超过int(11)的范围,因此64位机器上的结果被保存为int(11)的最大值:2147483647.于是在从数据库中取出的时候,便得到了错误的结果,会得到”127.255.255.255″这个ip地址.
解决的办法很多,比如可以用mysql的函数:INET_ATON和INET_NTOA来处理ip地址;或者把保存ip地址的字段改为bigint类型,这样在64位机器上虽然保存的是3395898803,使用long2ip函数仍能得到正确的结果.
仅供参考.

MySQL的新引擎

叫做Falcon,猎鹰的意思,名字够酷.
昨天看到这个消息的时候还着实使劲的期待了一下,不过看到了Peter Zaitsev的一篇文章,一下子就浇灭了我那可怜的盲目热情.这篇文章是对InnoDB,MyISAM和Falcon三种引擎性能的一个对比.从对比结果可以看出,Falcon和社会主义一样,还处于初级阶段.除了在READ_KEY_POINT这一项上有微弱的优势以外,几乎都严重的处于下风.不过另我欣慰的是,InnoDB的表现基本都要好于MyISAM,看来InnoDB确实是个不错的选择,除了支持事务和外键等特性,查询性能也至少不输给MyISAM,可以放心大胆的使用.

PS:今天看到Firefox有了3.0测试版本,虽然激动,还是忍住了没试用,怕的是用不了那些可爱的插件.如果没有插件,我宁可用IE了.

MySQL4的一个小bug

今天习惯的在命令行下输入”\s”查看数据库状态的时候,发现”Queries per second avg”这个值由原来的5k左右变成了只有几百,吓了一跳,以为数据库出了啥问题,就算优化的再好,也不可能下降到如此地步啊,可是查看前端服务和数据库都没有异常,难道MySQL计算这个数的时候出了问题?
于是查看MySQL的源代码,发现这个值是用总的Questions除以Uptime,就是用总的查询数除以服务器运行的时间,在源代码中,Questions被定义为无符号的长整型(ulong,范围是0~4294976295).所以当Questions超过4294976295时,就会重新回0,把当前的Questions数量加上4294976295,再除以Uptime,就会得到正确的”Queries per second avg”.
当然了,如果你看着很不爽,你可以重启MySQL来搞定它,hoho~~

PS:这个小bug在MySQL5中已经被修正
http://lists.mysql.com/commits/6833

已知的InnoDB与MyISAM表之间的差别

InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定。下面是已知的两者之间的差别,仅供参考。
1.InnoDB不支持FULLTEXT类型的索引。
2.InnoDB中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含where条件时,两种表的操作是一样的。
3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。
4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。
5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势。

从MySQL4到MySQL5

新版本总是意味着新的feature,但同时也意味着新的venture.
我们目前的数据库架构为读写分开的Master(1)+Slave(2),最近希望把版本由目前的4.1.18升级到5.0,为了稳妥起见,首先把其中一台Slave进行了升级,不久,问题就出现了,很多有unsigned属性的字段的值在Master和Slave上出现了不同。比如smallint(5) unsigned类型,Master上是0,Slave上却是65535。仔细一看,65535原来就是无符号类型的-1。测试一下,在Master上建立一个smallint(5) unsigned类型的字段,初始值为0,对它进行update操作,update test set test_unsigned=test_unsigned-1 where id=1;在Master(4.1.18)上,得到的值仍然为0,同步到Slave(5.0)上以后,值果然变成了65535。faint!
Google之,发现在MySQL5的manual中,详细的描述了MySQL4.1和MySQL5的区别,看来想全面升级到MySQL5,在操作unsigned类型字段时要十分小心,或者提前判断是否会产生小于0的值,或者使用类似下面的语句:UPDATE t SET i = CAST(i - 1 AS SIGNED);否则结果可能不是你想要的。
另我非常faint的是,在MySQL手册关于Master-Slave类型的replication的描述中,建议版本相同或者Master的版本低于Slave的版本,可是在上面的例子中,这明显有问题,或者怪我们程序判断的不严格?

给有重复记录的表添加唯一索引

不希望数据表中有重复记录的时候我们可以给表添加一个联合唯一索引
例如,user表中有user_id,user_name两个字段,如果不希望有两条一摸一样的的user_id和user_name,我们可以给user表添加两个字段的联合唯一索引:
alter table user add unique index(user_id,user_name);
这样当向表中添加相同记录的时候,会返回1062的添加失败信息。
但是有一种情况是表中已经有n个重复的记录,这时候我们才想起来要添加唯一索引,再执行上面的操作时,数据库会告诉你已经有重复的记录了,建立索引失败,这时候,我们可以用下面的操作:
alter ignore table user add unique index(user_id,user_name);
它会删除重复的记录(别怕,会保留一条),然后建立唯一索引,高效而且人性化。

MySQL出错代码

1005:创建表失败
1006:创建数据库失败
1007:数据库已存在,创建数据库失败
1008:数据库不存在,删除数据库失败
1009:不能删除数据库文件导致删除数据库失败
1010:不能删除数据目录导致删除数据库失败
1011:删除数据库文件失败
1012:不能读取系统表中的记录
1020:记录已被其他用户修改
1021:硬盘剩余空间不足,请加大硬盘可用空间
1022:关键字重复,更改记录失败
1023:关闭时发生错误
1024:读文件错误
1025:更改名字时发生错误
1026:写文件错误
1032:记录不存在
1036:数据表是只读的,不能对它进行修改
1037:系统内存不足,请重启数据库或重启服务器
1038:用于排序的内存不足,请增大排序缓冲区
1040:已到达数据库的最大连接数,请加大数据库可用连接数
1041:系统内存不足
1042:无效的主机名
1043:无效连接
1044:当前用户没有访问数据库的权限
1045:不能连接数据库,用户名或密码错误
1048:字段不能为空
1049:数据库不存在
1050:数据表已存在
1051:数据表不存在
1054:字段不存在
1065:无效的SQL语句,SQL语句为空
1081:不能建立Socket连接
1114:数据表已满,不能容纳任何记录
1116:打开的数据表太多
1129:数据库出现异常,请重启数据库
1130:连接数据库失败,没有连接数据库的权限
1133:数据库用户不存在
1141:当前用户无权访问数据库
1142:当前用户无权访问数据表
1143:当前用户无权访问数据表中的字段
1146:数据表不存在
1147:未定义用户对数据表的访问权限
1149:SQL语句语法错误
1158:网络错误,出现读错误,请检查网络连接状况
1159:网络错误,读超时,请检查网络连接状况
1160:网络错误,出现写错误,请检查网络连接状况
1161:网络错误,写超时,请检查网络连接状况
1062:字段值重复,入库失败
1169:字段值重复,更新记录失败
1177:打开数据表失败
1180:提交事务失败
1181:回滚事务失败
1203:当前用户和数据库建立的连接已到达数据库的最大连接数,请增大可用的数据库连接数或重启数据库
1205:加锁超时
1211:当前用户没有创建用户的权限
1216:外键约束检查失败,更新子表记录失败
1217:外键约束检查失败,删除或修改主表记录失败
1226:当前用户使用的资源已超过所允许的资源,请重启数据库或重启服务器
1227:权限不足,您无权进行此操作
1235:MySQL版本过低,不具有本功能

关于MySQL的性能优化

什么是我们能和应该优化的

  • Hardware
  • OS / libraries
  • SQL server (setup and queries)
  • API
  • Application
  • 优化硬件

  • 如果你需要大表(>2G),你应该考虑使用64位硬件,像Alpha,Sparc或者IA64.由于MySQL使用大量内部的64位整型,64位的CPU将有更好的表现.
  • 对于大数据库,优化顺序通常是内存,硬盘,CPU.
  • 更多的内存可以通过把更多的索引页保留在内存中来提高索引更新的速度
  • 如果你不使用事务安全表或者有一个大硬盘并且想避免大文件检查,有一个UPS是个好办法,它能在断电的时候使系统正常关闭.
  • 对于数据库运行在专用的服务器上的系统来说,应该考虑1G的网络,传输延迟和吞吐量同样重要.
  • 优化磁盘

  • 有专用的磁盘来运行系统,程序以及临时文件.如果更改很频繁,把更新日志和事务日志放在专用的磁盘上.
  • 对于数据库磁盘来说短寻道时间很重要;对于大表你可以预估需要:log(row_count) / log(index_block_length/3
  • 2/(key_length + data_ptr_length))+1 次查找来找到一行.对于一个有500000行的表要索引(medium int)log(500,000)/log(1024/3
  • 2/(3+4)) +1 = 4 次.上面的索引将需要500,000
  • 7
  • 3/2 = 5.2M,在实际文件中,大部分数据块将被缓冲,因此大概只需要1-2次查找.
  • 对写入操作你将需要(像上面一样)4次查找请求,为了找到索引存放的地方,通常要2次查找来更新索引和写入行.
  • 对实在大的数据库,你的应用将基于你的磁盘查找的速度,当你获得更多数据的时候,它以NlogN的速度增长.
  • 把数据库和表拆分到不同的磁盘上.在MySQL里你可以使用符号连接来实现.
  • RAID0将提高读和写
  • RAID0+1能提供安全性和提高读的速度.写操作将稍慢.
  • 不要在磁盘上使用镜像或者RAID(除了RAID0)用来存放临时文件或者为了数据能够恢复.
  • 在Linux下,的磁盘上启动时使用hdparm -m16 -d1开启多重扇面同时读写能力,和DMA.这可以提高5-50%的响应.
  • 在Linux上,用async(默认)和noatime来mount磁盘.
  • 对一些特殊的应用,有可能希望用一个ram磁盘存放特殊的表,但是通常这个不需要的.
  • 优化OS

  • 不要swap;如果你有内存问题,多加一些RAM来代替或者配置你的系统用更少的内存
  • 不要使用NFS磁盘来存储数据(会遇到NFS锁的问题).
  • 为系统和SQL服务器提高开放文件的数量(添加ulimit -n #在safe_mysqld脚本里).
  • 为系统提高处理器和线程的数量.
  • 如果有相对比较少的大表,告诉文件系统不要把文件分散到不同的柱面上(Solaris).
  • 使用支持大文件的文件系统(Solaris).
  • 选择使用哪个系统;Reiserfs在Linux上打开,读和写非常快.文件检查只需要几秒.
  • 选择API

  • PERL
  • OS和数据库之间可移植的程序
    对快速的原型设计有好处
    应该使用DBI/DBD接口

  • PHP
  • 比PERL简单
    比PERL使用更少的资源,使它更容易在Web服务器上使用.
    能通过升级到PHP4来获得更快的速度

  • C
  • 到MYSQL天然的接口
    更快,更容易控制
    更底层,因此你要做的更多

  • C++
  • 更高的级别给你更多的时间来编写你的应用
    仍在开发中

  • ODBC
  • 运行在Windows和Unix上
    几乎在不同的SQL服务器上可移植
    慢,MyODBC,是一个简单的穿透驱动比天然接口慢19%.
    很多途径做同样的事;像很多ODBC驱动一样在不同的区域有不同的bug很难运行.
    问题重重;Microsoft经常更改接口.
    不稳定的未来(Microsoft在OLE上比ODBC花更多的精力).

  • JDBC
  • 理论上在OS和数据库之间可移植
    可以在web客户端上运行

  • Python+others
  • 可能很好,但是我们不使用他们.

    优化应用程序

  • 应该有人专注于解决问题
  • 写应用程序的时候应该决定什么是最重要的:
  • 速度
    OS间可移植
    SQL服务器间可移植

  • 使用持续连接
  • 在你的应用程序中使用缓存来减少SQL服务器的压力.
  • 不要在你的应用程序中查询不需要的列.
  • 不要使用SELECT * FROM table_name…
  • 检查你的程序的所有部分,但是把努力放在检查整个应用下面最坏可能”合理”的压力上.
  • 如果一下子做很多改变,使用LOCK TABLES;例如很多UPDATE或者DELETE在一起的时候.
  • 可移植的应用程序应该使用:

  • Perl DBI/DBD
  • ODBC
  • JDBC
  • Python(或者任何其他有全面的SQL接口的语言)
  • 你应该只使用在所有的目标SQL服务器上存在的或者可以轻易被其他构造模仿的SQL构造.
  • 写封装来为其他的OS/SQL服务器提供缺少的功能.
  • 如果你需要更快的速度,你应该:

  • 找到瓶颈(CPU,磁盘,内存,SQL服务器,OS,API,或者应用程序)并专心解决他们
  • 使用能给你带来更多速度/灵活性的扩展
  • 了解你的SQL服务器以便于你在遇到问题或者避免瓶颈的时候使用可能最快的SQL构造
  • 优化你的表结构和查询
  • 使用备份来获得更多的select速度
  • 如果连接到数据库的网速很慢,使用压缩的客户端/服务器协议.
  • 不要担心你的第一个版本不是完全可移植的,当你解决了难题,优化总是可以稍后进行

    优化MySQL

  • 选择编译程序合编译选项
  • 为你的系统找到做好的MySQL启动选项
  • 学习MySQL手册,读Paul DuBois的MySQL著作
  • 使用EXPLAIN SELECT, SHOW VARIABLES, SHOW STATUS 和 SHOW PROCESSLIST.
  • 学习查询优化器是如何工作的.
  • 优化你的表结构
  • 维护你的表(myisamchk, CHECK TABLE, OPTIMIZE TABLE).
  • 使用MySQL扩展获得更快的速度.
  • 写一个MySQL UDF函数如果你发现你在很多地方需要这样的函数
  • 如果你不是确实需要,不要在表一级或者列一级使用GRANT
  • 付费给MySQL客服来获得帮助,解决问题:)
  • 编译和安装MySQL

  • 为你的系统选择最好的编译程序,通常可以获得10-30%更好的性能
  • 在Linux/Intel上,用pgcc编译MySQL.但是,二进制文件将只能运行在Pentium CPU上.
  • 对特殊的平台,使用MySQL手册总推荐的优化选项
  • 通常对特别的CPU(像Sparc的Sun工作站)本地的编译器会比gcc提供个个你好的性能,但是不总是这样.
  • 只用你将要使用的字符集编译MySQL
  • 把mysqld编译成静止可执行(使用–with-mysqld-ldflags=-all-static)并使用strip sql/mysqld去掉最终可执行.
  • 注意由于MySQL不使用C++异常,编译MySQL时去掉异常支持将获得很大性能的提升.
  • 如果你的OS支持,那么使用本地线程.
  • 使用MySQL性能测试来测试最终的二进制文件.
  • 维护

  • 如果可能,偶而运行OPTIMIZE table .这对于经常更新的可变大小的行非常重要.
  • 偶而使用myisamchk -a来更新你的表中索引的分布状态;记住做这个之前关闭MySQL.
  • 如果有文件碎片,把所有文件拷贝到另外的磁盘,清理旧磁盘再把文件拷回来或许很有意义.
  • 如果有问题,用myisamchk 或者CHECK table来检查你的表
  • 用 mysqladmin -i10 processlist extended-status 监视MySQL状态
  • 用mysqladmin debug 来获得锁和性能的信息
  • 优化SQL
    把SQL用在它擅长的地方,用应用程序做其他事.用SQL服务器来做:

  • 通过where条件找到行
  • 联合表
  • GROUP BY
  • ORDER BY
  • DISTINCT
  • 不要用SQL服务器做:

  • 检查数据(像日期)
  • 作为计算器
  • Tips

  • 精明的使用索引
  • 索引对搜索有好处,但是对插入/更新索引所在列没好处
  • 保持数据符合第三范式,但是不要怕重复信息或者在需要更快速度的时候建立摘要表.
  • 用建立和查询大表的摘要表来代替在一个大表上进行多次GROUP BY操作.
  • UPDATE table set count=count+1 where key_column=constant非常快.
  • 对日志表,偶而从他们中生产摘要表可能比让摘要表一直存在要好.
  • INSERT的时候利用默认值的优点
  • 不同SQL服务器之间的不同速度
    Reading 2000000 rows by key: NT Linux
    mysql 367 249
    mysql_odbc 464
    db2_odbc 1206
    informix_odbc 121126
    ms-sql_odbc 1634
    oracle_odbc 20800
    solid_odbc 877
    sybase_odbc 17614

    Inserting (350768) rows: NT Linux
    mysql 381 206
    mysql_odbc 619
    db2_odbc 3460
    informix_odbc 2692
    ms-sql_odbc 4012
    oracle_odbc 11291
    solid_odbc 1801
    sybase_odbc 4802

    在上面的测试中,MySQL运行于8M的缓存,其他数据库运行在默认安装上.

    重要的MySQL启动选项
    back_log Change if you do a lot of new connections.
    thread_cache_size Change if you do a lot of new connections.
    key_buffer_size Pool for index pages; Can be made very big
    bdb_cache_size Record and key cache used by BDB tables.
    table_cache Change if you have many tables or simultaneous connections
    delay_key_write Set if you need to buffer all key writes
    log_slow_queries Find queries that takes a lot of time
    max_heap_table_size Used with GROUP BY
    sort_buffer Used with ORDER BY and GROUP BY
    myisam_sort_buffer_size Used with REPAIR TABLE
    join_buffer_size When doing a join without keys

    优化表

  • MySQL有丰富的类型.你应该为每一列选择最有效的类型
  • ANALYSE过程能帮助你找到一个表的最佳类型:SELECT * FROM table_name PROCEDURE ANALYSE()
  • 使用NOT NULL 将不保存空值.这对建立索引的列尤为重要.
  • 把你的表由ISAM类型改变为MyISAM类型
  • 如果可能,用固定表格式建立表.
  • 不会使用的时候不要建立索引
  • 记住MySQL可以在索引的前缀上进行搜索;如果你有INDEX (a,b),就不必在(a)上建立索引.
  • 在CHAR/VARCHAR列上建立索引的时候,用建立前缀索引来节省空间.CREATE TABLE table_name (hostname CHAR(255) not null, index(hostname(10)))
  • 为每个表选择最有效的类型
  • 不同表中的同样信息的列应该同样定义并且有同样的名字.
  • MySQL如何存储数据

  • 数据按目录存放
  • 表以文件的形式存放
  • 列以变长或者固定尺寸的格式存放.在BDB表中数据按页存放
  • 支持基于内存的表
  • 数据库和表可以从不同的磁盘上做符号连接
  • 在Windows上MySQL支持对数据库通过.sym文件做内部的符号连接
  • MySQL表类型

  • HEAP表;只存在于内存中的固定行尺寸表,用哈希索引
  • ISAM表;MySQL3.22中的老的B树表
  • MyISAM表;包括大量扩展的ISAM表的新版本:
  • 二进制可移植
    空值列上的索引
    动态尺寸列上比ISAM表更少的碎片
    支持大文件
    更好的索引压缩
    更好的关键字统计
    更好并且更快的auto_increment 处理

  • 从Sleepycat来的Berkeley DB (BDB):事务安全(通过BEGIN WORK / COMMIT | ROLLBACK).
  • MySQL行类型(有关ISAM/MyISAM表)

  • 如果每列都是固定长度的格式(没有VARCHAR,BLOB或者TEXT列)MySQL将建立固定尺寸的表格式,否则,表被建立成动态尺寸格式
  • 固定尺寸比动态尺寸格式格式更快也更安全
  • 动态尺寸格式的行通常占更少的空间但是如果表经常更新会一直产生碎片
  • 有时候为了提高主表的速度把所有的VARCHAR,BLOB和TEXT列转移到其他表中是值得的.
  • 用myisampack (ISAM中用pack_isam )可以建立一个只读的,打包的表.它最小的利用磁盘空间在慢磁盘时效果很好.打包的表最好用在不会更新的日志表上.
  • MySQL缓存(一旦分配,所有线程共享)

  • 关键字缓存:key_buffer_size,默认8M
  • 表缓存;table_cache,默认64
  • 线程缓存;thread_cache_size,默认0
  • 域名缓存;在编译时可以更改,默认128
  • 内存地址表;目前只用在压缩表上.
  • 注意MySQL没用行缓存,让OS来处理这个.

    MySQL缓冲变量(通过命令分配,不共享)

  • sort_buffer ; ORDER BY / GROUP BY
  • record_buffer ;扫描表
  • join_buffer_size :不通过关键字连接
  • myisam_sort_buffer_size :REPAIR TABLE
  • net_buffer_length ;用来读SQL语句和缓冲结果
  • tmp_table_size;临时结果的HEAP表尺寸
  • Continue reading →

    Sql Relay

    Sql Realy是SF上的一个项目,它实现了数据库连接池,同时它也可以实现负载均衡,按照文档的说法”In effect, SQL Relay is a very specialized Load Balancer”.
    连接池可以有效的减少连接带来的开销,因此Sql Relay和Mysql一起使用,似乎是个不错的主意.除了连接的开销,大量并发读写造成的锁表问题也是优化Mysql时要考虑的问题,我们在提高Mysql数据库应付大并发访问能力的时候,一个常见的方法是使用Master-Slave结构使读写分开,主写从读,从而避免大量读操作造成的锁表,必要时可以使用多个Slave服务器来分担压力,虽然Sql Relay可以作为一个load balancer,但是它并不能区分一个操作是读还是写,因此,我们可以用Sql Relay来专门对付那些Slave.
    Sql Relay可以在SF上下载,同时还需要Rudiments.

    安装过程:
    解压缩,首先安装Rudiments,非常简单,make;make install就搞定
    然后安装Sql Relay,注意本机上需要首先安装Mysql,因为Sql Relay在安装的时候需要Mysql的一些include和lib中的文件.
    在configure时指定Sql Relay和Mysql的安装路径:
    configure –prefix=/usr/local/sqlrelay –with-mysql-prefix=/usr/local/mysql/
    然后 make 和make install

    配置
    到etc目录中,cp sqlrelay.conf.example sqlrelay.conf
    Continue reading →