生命之中的最大错误在于:终日担心犯错误。— 爱尔伯特·哈伯德 (Elbert Hubbard 1856-1915),《笔记》
分页: 1/5 第一页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]

目前使用MySQL的网站,多半同时使用Memcache作为键值缓存。虽然这样的架构极其流行,有众多的案例,但过于依赖Memcache,无形中让Memcache成为故障的根源:

  • Memcache数据一致性的问题:当MySQL数据变化后,如果不能及时有效的清理掉过期的数据,就会造成数据不一致。这在强调即时性的Web2.0时代,不可取。
  • Memcache崩溃后的雪崩效应:作为缓存的Memcache一旦崩溃,MySQL很可能在短时间内承受高负载而宕机。据说前段时间新浪微博就遭遇了这样的问题。

注:关于清理过期数据的问题,可以在程序架构上想办法,如果数据操作有统一DAO封装的话,可以利用Observer模式来清理过期数据,非主题内容,资料自查。

面对这些问题,HandlerSocket项目是个不错的解决方案,它通过插件的方式赋予MySQL完整的NoSQL功能,从原理上讲,它跳过MySQL中最耗时的语法解析,查询计划等步骤,直接读取数据,如果内存够大,能装下索引,MySQL的查询效率能提高若干倍!

性能测试:Using MySQL as a NoSQL – A story for exceeding 750,000 qps

因为HandlerSocket的性能足够好,所以就没有必要使用Memcache了,能节省大量的硬件资源,相当低碳!而且HandlerSocket操作的是MySQL放在内存中的索引,没有额外的缓存,所以自然就不存在数据一致性的问题。

安装

如果使用Percona Server版本的MySQL就简单了,因为它已经内置了HandlerSocket支持,不过考虑到其内置的版本不够新,存在一些早已修复的BUG,所以最好采用源代码编译。

注:旧版本HandlerSocket的一些问题可参见:What’s up with HandlerSocket?

官方已经有了一份简单的安装文档,但在我实际安装时,遇到了一些其他未说明的问题,所以这里就把相应的安装过程再写一遍。

首先要确保已经安装了MySQL5.1以上的版本,我用的是Ubuntu操作系统,事先已经用apt安装了MySQL5.1.37,同时还需要相应的mysql_config,如果是Ubuntu的话,可以:

shell> aptitude install libmysqld-dev

注:如果你用的MySQL是从源代码编译的或官方提供的二进制版本,可以略过此步。

接着下载一份和系统MySQL版本一致的MySQL源代码和HandlerSocket源代码:

shell> tar zxf mysql-5.1.37.tar.gz shell> tar zxf ahiguti-HandlerSocket-Plugin-for-MySQL-1.0.6-76-gf5f7443.tar.gz shell> cd ahiguti-HandlerSocket-Plugin-for-MySQL-f5f7443 shell> ./autogen.sh shell> ./configure --with-mysql-source=../mysql-5.1.37 \                    --with-mysql-bindir=/usr/bin \                    --with-mysql-plugindir=/usr/lib/mysql/plugin

其中的参数含义如下:with-mysql-source表示MySQL源代码目录,with-mysql-bindir表示MySQL二进制可执行文件目录(也就是mysql_config所在目录),with-mysql-plugindir表示MySQL插件目录,如果不清楚这个目录在哪,可以按如下方法查询:

mysql> SHOW VARIABLES LIKE 'plugin%'; +---------------+-----------------------+ | Variable_name | Value                 | +---------------+-----------------------+ | plugin_dir    | /usr/lib/mysql/plugin | +---------------+-----------------------+

运行命令后,如果你使用的是MySQL5.1.37版本的话,会遇到如下错误信息:

MySQL source version does not match MySQL binary version

明明我们的MySQL源代码版本和二进制版本都是5.1.37,为什么还会出现这个错误呢?通过查询HandlerSocket的编译脚本,发现原来它会检索MySQL源代码目录中的VERSION文件,可MySQL5.1.37的源代码目录里不知何故竟然没有这个文件,所以就报错了,既然知道了原因,那我们就照猫画虎做一个VERSION文件放到MySQL源代码目录,内容如下:

MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=1 MYSQL_VERSION_PATCH=37 MYSQL_VERSION_EXTRA=

再次运行configure脚本,应该就OK了,把剩下的步骤进行完:

shell> make shell> make install

接着需要配置一下HandlerSocket,编辑MySQL配置文件,加入如下内容:

[mysqld] loose_handlersocket_port = 9998 # the port number to bind to (for read requests) loose_handlersocket_port_wr = 9999 # the port number to bind to (for write requests) loose_handlersocket_threads = 16 # the number of worker threads (for read requests) loose_handlersocket_threads_wr = 1 # the number of worker threads (for write requests) open_files_limit = 65535 # to allow handlersocket accept many concurrent # connections, make open_files_limit as large as # possible.

此外,InnoDB的innodb_buffer_pool_size,或MyISAM的key_buffy_size等关系到缓存索引的选项尽可能设置大一些,这样才能发挥HandlerSocket的潜力。

注:apt包管理下的配置文件一般是/etc/mysql/my.cnf,否则一般是/etc/my.cnf

最后登陆MySQL并激活HandlerSocket插件:

mysql> INSTALL PLUGIN handlersocket soname 'handlersocket.so';

重启一下MySQL服务,如果没有问题,就能在MySQL里看到HandlerSocket的线程了:

mysql> SHOW PROCESSLIST;

也可以通过查询刚配置的端口是否已经被MySQL占用来确认是否安装成功:

shell> lsof -i :9998 shell> lsof -i :9999

完活儿!现在你的MySQL已经具备NoSQL的能力了!

实战

首先创建一个测试用的表:

CREATE TABLE IF NOT EXISTS `test`.`t` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `a` varchar(10) NOT NULL,   `b` varchar(10) NOT NULL,   PRIMARY KEY (`id`),   KEY `a_b` (`a`,`b`) ) ENGINE=InnoDB;

注:理论上HandlerSocket支持MyISAM,InnoDB等各种引擎,不过推荐使用InnoDB。

HandlerSocket的协议非常简单,指令通过TAB分割,一行就是一个请求。本文用到了:

  • 打开索引:P <索引标识> <数据库> <表> <索引> <字段>
  • 插入数据:<索引标识> ‘+’ <参数个数> <参数1> … <参数N>
  • 读取数据:<索引标识> <操作> <参数个数> <参数1> … <参数N> <条数> <偏移>

SQL原型:INSERT INTO test.t (id, a, b) VALUES (1, ‘a1′, ‘b1′), (2, ‘a2′, ‘b2′)

shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P       1       test    t       PRIMARY id,a,b 0       1 1       +       3       1       a1      b1 0       1       0 1       +       3       2       a2      b2 0       1       0

注:使用HandlerSocket时,因为没有实际运行SQL,所以Binlog记录的是Row格式。

SQL原型:SELECT id, a, b FROM test.t WHERE id = 1 LIMIT 1

shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P       1       test    t       PRIMARY id,a,b 0       1 1       =       1       1       1       0 0       3       1       a1      b1

SQL原型:SELECT id, a, b FROM test.t WHERE id >= 1 LIMIT 2

shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P       1       test    t       PRIMARY id,a,b 0       1 1       >=      1       1       2       0 0       3       1       a1      b1      2       a2      b2

SQL原型:SELECT id, a, b FROM test.t WHERE a = ‘a1′ AND b = ‘b1′ LIMIT 1

shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P       1       test    t       a_b     id,a,b 0       1 1       =       2       a1      b1      1       0 0       3       1       a1      b1

对HandlerSocket一个常见的误解是只能执行PRIMARY类型的KV查询,实际上只要支持索引,一般的简单查询它都能胜任,篇幅所限,这里就不多说了,如果你觉得直接操作telnet有些吃力,也可以使用自己熟悉的客户端来测试,官方文档里有介绍。

注:HandlerSocket作者写了一个不错的PPT可以参考:HandlerSocket plugin for MySQL

记:MySQL5.6提供原生的Memcached API,实际就是KV型NoSQL了,但HandlerSocket并不局限于KV形式,所以仍然有生存空间。

互联网技术发展犹如一列高速运行的火车,下一站:HandlerSocket!大家做好准备吧。

原文:http://huoding.com/2011/04/10/62

昨天到今天,一直有个sql语句让我很郁闷

#1054 - Unknown column '808' in 'where clause'

SELECT max( ma.magid ) magid
FROM aslibra.z_magazine ma
LEFT JOIN test.mag m ON m.id = ma.magid
WHERE ma.categoryid = 808
AND m.pub = '1'
GROUP BY ma.categoryid
LIMIT 0 , 30


一个查询语句怎么会多做事一个列呢?
在前后加上单引号,选出的数据是 categoryid=0的,更加郁闷了,明显不应该~~
虽然人老了,可脑子还没有退化到写错sql的地步

今天发现了问题,做url地址时href="xxx?id=808"
点击后发现地址栏不对,=和808之间有空格

估计是特殊字符,urlencode结果是 “%EF%BB%BF808”
前面真的是特殊字符!

这个文本是从excel复制的,问题出现在此
从excel复制文本的童鞋要注意了。。。以此为戒。。 再复制一次即可
把这个文本再复制,粘贴到另外一个文本,就正常了。
Tags: , ,
不用代码框括起来了,直接就是文本吧,#的行是注释
下面的是真实的例子,可供参考:

[ root@aslibra www.aslibra.com ]# mysql -S /Data/www.aslibra.com/mysql/mysql.sock -uadmin -ppassword
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 322891
Server version: 5.5.2-m2-log Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

#显示当前所有日志
mysql> show master logs;
+------------------+------------+
| Log_name         | File_size  |
+------------------+------------+
| mysql-bin.000001 |        126 |
| mysql-bin.000002 | 1074328576 |
| mysql-bin.000003 |  918443740 |
| mysql-bin.000004 |        126 |
| mysql-bin.000005 |        126 |
| mysql-bin.000006 |  109880744 |
+------------------+------------+
6 rows in set (0.00 sec)

#删除日志到某一个,不能超过最后一个
mysql> purge master logs to 'mysql-bin.000027';
ERROR 1373 (HY000): Target log not found in binlog index

#删除日志到最后一个即可
mysql> purge master logs to 'mysql-bin.000006';
Query OK, 0 rows affected (3.80 sec)

#看看现在的情况
mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000006 | 109884395 |
+------------------+-----------+
1 row in set (0.00 sec)

#退出
mysql> exit
Tags:
此需求的可能性:

做所有的数据库同步需要很多无用的空间,如果仅仅用到其中一个数据库,那就做一个数据库的同步就足够了。

步骤一 主数据库开通replication用户

按需求不一样名称和密码以及IP不同:
CREATE USER 'slave'@'192.168.1.2' IDENTIFIED BY '***';
GRANT REPLICATION SLAVE ON * . * TO 'slave'@'192.168.1.2' IDENTIFIED BY '***' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;


步骤二 取得当前数据备份,备份mysql库和你要的database2

方式1 从master取得

FLUSH TABLES WITH READ LOCK; //锁定所有表
show master status; //取得当前日志点
//打包文件或者是直接导出数据,比停止服务好的地方就是有一段读数据库的时间
unlock tables; //解锁
Tags: ,
今天发现phpMyadmin3.3版本有两个新功能很实用:
1 Synchronize是支持两个数据库同步的操作,这功能挺好的
2 管理replication

不过,同步操作似乎是经过本地web管理的服务器,如果是远端的数据库同步,可能不太合适了,未确认。除非把管理的web端放在数据库的局域网,那样应该挺快。

复制的管理也蛮好,把平时需要输入的命令行给做成点击几下就可以,很方便,这个实用。

phpmyadmin官网下载最新版本吧!
点击这里查看官方关于同步功能的介绍
Tags: ,
mysql的安装目录里有support-files,里面有几份默认的配置
分别是 huge large medium 等,还有高压力的InnoDB的参考:

[root@aslibra support-files]# grep -v ^# my-huge.cnf
key_buffer = 384M
table_cache = 512
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 32M
thread_concurrency = 8
Tags:
如果你的服务和我的问题类似,则不妨参考此项做法(只是临时迁移):

A数据库服务是在3306,数据库连接用的是hosts里的名称,要迁移到B数据库,但端口服务是3307
在不改PHP代码的前提下,可以这样:

1 先用iptables设置B服务器的3306端口转发到3307:

iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 3306 -j DNAT --to-destination :3307


这里限制了eth1

2 相应的用户导入,如果不知道用户密码,可以导入相应的mysql/usr表里的相应记录,如果有表权限分配,则比较复杂了,这个多熟悉一下数据库操作才行

3 导出数据并导入,当然了,也需要创建相应的库

mysqldump -S /Data/mysqldb/3306/mysql.sock -uu -pp aslibra >aslibra.sql
mysql -h 192.168.1.8 -P3307 -uu -pp aslibra < aslibra.sql


这里用户是u,密码是p,可以在此服务器访问目标数据库

4 修改hosts相应的记录为B的IP,OK

Tags: ,
分页: 1/5 第一页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐