标签:mysql

浏览模式: 标准 | 列表 | 图文
mac下ruby 安装 mysql2真是一堆坑

mac下ruby 安装 mysql2真是一堆坑

直接 gem install mysql2报错。确实很烦人,因为我 mysql 本身本机没有,所以就不太可能安装 mysql-client 之类的。于是安装了 mysql-client。但还是报错。无法编译。

看网上的文章是安装 mariadb,然后指定 mysql-config 就 OK 了。我已经懒得弄了。。。。。
你看 postgresql 多方便,安装失败的时候 ,提示你 brew install libpq,就行了(确实是在我 install libpq 后,gem 就走完了)
真不知道那些本地没有 mysql 的人是怎么忍受得了 mysql2这样的库的(也可能只是我受不了吧)
---
问了一下 gpt,他说我安装好 mysql-client 后,还要指定一下:
export LDFLAGS="-L/usr/local/opt/mysql-client/lib"
export CPPFLAGS="-I/usr/local/opt/mysql-client/include"
然后再运行就 OK 了。于是我又重新 retry 了一下。但还是失败了
--
如果要成功就参考这个吧:https://medium.com/@0x88/%E5%9C%A8-macos-%E7%84%A1%E7%97%9B%E5%AE%89%E8%A3%9D-ruby-mysql2-gem-apple-m1-intel-mac-%E9%81%A9%E7%94%A8-330f996ae3c7,我是不想再试了。要么 sqlite ,要么 pgsql 吧
Error connecting remote MySQL server [ERROR 1042 (HY000): Can't get hostname for your address]

Error connecting remote MySQL server [ERROR 1042 (HY000): Can't get hostname for your address]

设置了远程数据库允许IP连接,也设置了bind ip为0.0.0.0 ,但有时候能连,有时候不能连接,而且还设置了是IP连接,报标题所在的错误,即 [ERROR 1042 (HY000): Can't get hostname for your address]。

开始就在想,是不是skip-name-resolve的问题,但因为我不是用host连接的,也不是内部的域名解析的问题。所以开始没注意,但google了之后,还是决定加了skipnameresolve

ave MySQL 5.5 Server setup on a windows machine. I am able to connect to the server from console / app running on the same machine but not from a remote machine. While connecting using the command

mysql -h xx.xx.xx.xx --port=3306 -u root -p
I get error as:

ERROR 1042 (HY000): Can't get hostname for your address
Have tried putting entry of client ip in server's etc\hosts file as

<client-ip> <client-hostname>
所有的回答都指向了skip-name-resolve
I believe this is to do with the fact that MySQL tries to establish the DNS name associated with your IP address on connect. See here for more information at the MySQL site.

You have two options:

1) Fix the connecting machine's reverse DNS. Since you've already added the machine to the hosts file, this might be unnecessary. You should also issue a FLUSH HOSTS statement on the MySQL server. See the same link above for more information about this.

2) Run MySQL with the '--skip-name-resolve' option. However, if you do this, you won't be able to use DNS names in GRANT statements. Instead you'll be restricted to using IP addresses.

2.1) or put in my.ini :

[mysqld]
skip-name-resolve
I'd recommend (1) if you can.

Hope this helps.
然后也确实解决了这个问题。记录一下

为什么我的vps在重启后mysql都不能启动?

为什么我的vps在重启后mysql都不能启动?

为什么我的vps在重启后mysql都不能启动?带着这个问题,我看了很多信息,比如rc0.d/~rc6.d这些目录。一个个里面都有mysql的启动脚本。那为什么还是不能启动呢?

在vampire的提示下。看了:dmesg | grep mysql,结果返回空。

然后又运行了:cat /var/log/daemon.log,仔细翻了一下,居然发现了一条这个:

Nov 7 21:53:36 vpsname /etc/init.d/mysql[988]: ERROR: The partition with /var/lib/mysql is too full!

咦。这是什么??怎么会满了?然后我ls -la /var/lib/mysql

我靠:

lrwxrwxrwx 1 mysql mysql 29 Dec 10 2012 mysql -> /server/???/mysql/mysql/

得,原来我mysql的存储是放在/server/盘下面,/server盘是什么?df -h看了一下:

/dev/xvdb 30G 3.7G 25G 14% /server

原来是我挂载的硬盘啊。

于是我一下子心里就明白了。我在rc.local里写了一句:mount xxx xxxx,但是启动mysql在mount前面,所以。。。。

到这里我就明白了,要么。我在mount后面主动启动一下,要么我将/server的信息写到/etc/fastab里面。二选一。

我最终还是偷懒了。怎么做,我不告诉你们

MYSQL 存储过程

MYSQL 存储过程

说实话,关于存储过程的博客还真的不多,有几个是值得看一下的

1、官方;http://dev.mysql.com/doc/refman/5.1/zh/stored-procedures.html

2、http://www.netingcn.com/tag/%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B

3、http://blog.why100000.com/?p=711

也发现,如果不做复杂查询,存储过程对我来说几乎没有,本来是想解决查找GEO相关的信息的,但发现这样的SQL:

SELECT userid,lat,lng,gender,
( 6371 * acos( cos( radians(31.000700) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(120.000099) ) + sin( radians(31.000700) ) * sin( radians( lat ) ) ) ) AS distance
FROM `user_geo` WHERE last_activity_time > '2013-03-11 00:00:00'
ORDER BY distance ASC limit 100

这其中的复杂度就在于distance每次都要计算,所以我尝试换成了存储过程:

DROP PROCEDURE IF EXISTS search_around_user;
DELIMITER //
CREATE PROCEDURE search_around_user
(
s_lat float(10,6),
s_lng float(10,6),
s_last_act datetime,
s_gender tinyint,
s_number tinyint,
s_page tinyint
)
LABEL_PROC:
BEGIN
if s_number <= 1 then
set s_number = 20;
end if;
if s_page <= 0 then
set s_page = 0;
end if;
if s_gender <= 0 then
set @genderQuery = "";
else
set @genderQuery = concat(" and gender = " , s_gender , " ");
end if;
set @limitQuery = concat("LIMIT " , s_page * s_number , " , " , s_number , " ");

set @strsql = CONCAT("select userid, ",
"( 6371 * acos( cos( radians(",s_lat,") ) * cos( radians( lat ) ) * cos( radians( lng ) - radians( ",s_lng," ) ) ",
"+ sin( radians( ",s_lat," ) ) * sin( radians( lat ) ) ) ) AS distance ",
" FROM user_geo where last_activity_time >= '", s_last_act , "' " , @genderQuery , " ORDER BY distance " , @limitQuery) ;

prepare stmtsql from @strsql;
execute stmtsql;


END LABEL_PROC;
//
DELIMITER ;

然后再次调用:

call search_around_user(31.000700,120.000099,'2013-03-11 00:00:00',0,20,0)

所耗费的时间和上述直接写SQL的时间是几乎一样的。想来,这也是因为distance的计算不能被优化而导致的。。。于是乎,放弃用存储过程

MySQL STRAIGHT_JOIN 与 NATURAL JOIN

MySQL STRAIGHT_JOIN 与 NATURAL JOIN

这是一篇文档的简要介绍,本来没有想过要提的,因为我以前真没用过straight join,看到这个名词其实是老王的一句话,他说,利用这个优化了SQL,于是就看了一下。果然发到了这句话:

STRAIGHT_JOIN 实际上与内连接 INNER JOIN 表现完全一致,不同的是使用了 STRAIGHT_JOIN 后,table1 会先于 table2 载入。
提示
MySQL 在执行 INNER JOIN 的时候,会根据自己内部的优化规则来决定先载入 table1 还是 table2,如果您确认 MySQL 载入表的顺序并不是最优化的时候,就可以使用 STRAIGHT_JOIN 以替代 INNER JOIN。

我参考的这页,说是关于mysql 的join有五篇:

本章节内容共分 5 部分:

  1. 1. MySQL JOIN 语法说明与 INNER JOIN 语法用法实例
  2. 2. MySQL LEFT JOIN 语法用法与实例
  3. 3. MySQL RIGHT JOIN 语法用法与实例
  4. 4. MySQL JOIN 多表连接
  5. 5. MySQL STRAIGHT_JOIN 与 NATURAL JOIN
  6. 确实 是值得一看。
MySQL中show语法

MySQL中show语法

我知道,你看到下面的内容,一定没有兴趣往下读,实在太乱了,所以我准备了两份PDF,希望你们读起来会方便一点(两种不同的排版方式,看各位喜欢了)

1、第一份,原网站的排版:uploadify-v2.1.4-www.7es.cn.rar

2、我自己整理的markdown格式的排版:a59353ca1daaaf38e0787e6145eddae9

mysql show命令

show databases;

show tables from db_name;

show columns from table_name from db_name;

show index from talbe_name [from db_name];

show status;

show variables;

show [full] processlist;

show table status [from db_name];

show grants for user;

除了status,processlist和grants外,其它的都可以带有like wild选项,它可以使用SQL的'%'和'_'字符;

show databases like '%t';

将会列出所有数据库名字末尾为't'字符的数据库

当然了,在这些sql中,你也可以用db_name.table_name来代替 table_name from db_name这样写会更简便些!

如果一个用户没有一个表的任何权限,表将不在SHOW TABLES或mysqlshow db_name中的输出中显示

大家可能还记得describe table_name ,它实现的是与show columns from db_name.table_name一样的效果

show status将可以用mysqlshow --status 来得到同样的效果

  • 列 含义
  • Name 表名
  • Type 表的类型 (ISAM,MyISAM或HEAP)
  • Row_format 行存储格式 (固定, 动态, 或压缩)
  • Rows 行数量
  • Avg_row_length 平均行长度
  • Data_length 数据文件的长度
  • Max_data_length 数据文件的最大长度
  • Index_length 索引文件的长度
  • Data_free 已分配但未使用了字节数
  • Auto_increment 下一个 autoincrement(自动加1)值
  • Create_time 表被创造的时间
  • Update_time 数据文件最后更新的时间
  • Check_time 最后对表运行一个检查的时间
  • Create_options 与CREATE TABLE一起使用的额外选项
  • Comment 当创造表时,使用的注释 (或为什么MySQL不能存取表信息的一些信息)。

SHOW FIELDS是SHOW COLUMNS一个同义词,SHOW KEYS是SHOW INDEX一个同义词。你也可以用mysqlshow db_name tbl_name或mysqlshow -k db_name tbl_name 列出一张表的列或索引。

SHOW INDEX以非常相似于ODBC的SQLStatistics调用的格式返回索引信息。下面的列被返回:

列 含义

Table 表名

Non_unique 0,如果索引不能包含重复。

Key_name 索引名

Seq_in_index 索引中的列顺序号, 从 1 开始。

Column_name 列名。

Collation 列怎样在索引中被排序。在MySQL中,这可以有值A(升序) 或NULL(不排序)。

Cardinality 索引中唯一值的数量。这可通过运行isamchk -a更改.

Sub_part 如果列只是部分被索引,索引字符的数量。NULL,如果整个键被索引。

SHOW STATUS提供服务器的状态信息(象mysqladmin extended-status一样)。输出类似于下面的显示,尽管格式和数字可以有点不同:

+--------------------------+--------+

| Variable_name | Value |

+--------------------------+--------+

| Aborted_clients | 0 |

| Aborted_connects | 0 |

| Connections | 17 |

| Created_tmp_tables | 0 |

| Delayed_insert_threads | 0 |

| Delayed_writes | 0 |

| Delayed_errors | 0 |

| Flush_commands | 2 |

| Handler_delete | 2 |

| Handler_read_first | 0 |

| Handler_read_key | 1 |

| Handler_read_next | 0 |

| Handler_read_rnd | 35 |

| Handler_update | 0 |

| Handler_write | 2 |

| Key_blocks_used | 0 |

| Key_read_requests | 0 |

| Key_reads | 0 |

| Key_write_requests | 0 |

| Key_writes | 0 |

| Max_used_connections | 1 |

| Not_flushed_key_blocks | 0 |

| Not_flushed_delayed_rows | 0 |

| Open_tables | 1 |

| Open_files | 2 |

| Open_streams | 0 |

| Opened_tables | 11 |

| Questions | 14 |

| Slow_queries | 0 |

| Threads_connected | 1 |

| Threads_running | 1 |

| Uptime | 149111 |

+--------------------------+--------+

上面列出的状态变量有下列含义:

  • Aborted_clients 由于客户没有正确关闭连接已经死掉,已经放弃的连接数量。
  • Aborted_connects 尝试已经失败的MySQL服务器的连接的次数。
  • Connections 试图连接MySQL服务器的次数。
  • Created_tmp_tables 当执行语句时,已经被创造了的隐含临时表的数量。
  • Delayed_insert_threads 正在使用的延迟插入处理器线程的数量。
  • Delayed_writes 用INSERT DELAYED写入的行数。
  • Delayed_errors 用INSERT DELAYED写入的发生某些错误(可能重复键值)的行数。
  • Flush_commands 执行FLUSH命令的次数。
  • Handler_delete 请求从一张表中删除行的次数。
  • Handler_read_first 请求读入表中第一行的次数。
  • Handler_read_key 请求数字基于键读行。
  • Handler_read_next 请求读入基于一个键的一行的次数。
  • Handler_read_rnd 请求读入基于一个固定位置的一行的次数。
  • Handler_update 请求更新表中一行的次数。
  • Handler_write 请求向表中插入一行的次数。
  • Key_blocks_used 用于关键字缓存的块的数量。
  • Key_read_requests 请求从缓存读入一个键值的次数。
  • Key_reads 从磁盘物理读入一个键值的次数。
  • Key_write_requests 请求将一个关键字块写入缓存次数。
  • Key_writes 将一个键值块物理写入磁盘的次数。
  • Max_used_connections 同时使用的连接的最大数目。
  • Not_flushed_key_blocks 在键缓存中已经改变但是还没被清空到磁盘上的键块。
  • Not_flushed_delayed_rows 在INSERT DELAY队列中等待写入的行的数量。
  • Open_tables 打开表的数量。
  • Open_files 打开文件的数量。
  • Open_streams 打开流的数量(主要用于日志记载)
  • Opened_tables 已经打开的表的数量。
  • Questions 发往服务器的查询的数量。
  • Slow_queries 要花超过long_query_time时间的查询数量。
  • Threads_connected 当前打开的连接的数量。
  • Threads_running 不在睡眠的线程数量。
  • Uptime 服务器工作了多少秒。

关于上面的一些注释:

如果Opened_tables太大,那么你的table_cache变量可能太小。

如果key_reads太大,那么你的key_cache可能太小。缓存命中率可以用key_reads/key_read_requests计算。

如果Handler_read_rnd太大,那么你很可能有大量的查询需要MySQL扫描整个表或你有没正确使用键值的联结(join)。

SHOW VARIABLES显示出一些MySQL系统变量的值,你也能使用mysqladmin variables命令得到这个信息。如果缺省值不合适,你能在mysqld启动时使用命令行选项来设置这些变量的大多数。输出类似于下面的显示,尽管格式和数字可以有点不同:

+------------------------+--------------------------+

| Variable_name | Value |

+------------------------+--------------------------+

| back_log | 5 |

| connect_timeout | 5 |

| basedir | /my/monty/ |

| datadir | /my/monty/data/ |

| delayed_insert_limit | 100 |

| delayed_insert_timeout | 300 |

| delayed_queue_size | 1000 |

| join_buffer_size | 131072 |

| flush_time | 0 |

| interactive_timeout | 28800 |

| key_buffer_size | 1048540 |

| language | /my/monty/share/english/ |

| log | OFF |

| log_update | OFF |

| long_query_time | 10 |

| low_priority_updates | OFF |

| max_allowed_packet | 1048576 |

| max_connections | 100 |

| max_connect_errors | 10 |

| max_delayed_threads | 20 |

| max_heap_table_size | 16777216 |

| max_join_size | 4294967295 |

| max_sort_length | 1024 |

| max_tmp_tables | 32 |

| net_buffer_length | 16384 |

| port | 3306 |

| protocol-version | 10 |

| record_buffer | 131072 |

| skip_locking | ON |

| socket | /tmp/mysql.sock |

| sort_buffer | 2097116 |

| table_cache | 64 |

| thread_stack | 131072 |

| tmp_table_size | 1048576 |

| tmpdir | /machine/tmp/ |

| version | 3.23.0-alpha-debug |

| wait_timeout | 28800 |

+------------------------+--------------------------+

SHOW PROCESSLIST显示哪个线程正在运行,你也能使用mysqladmin processlist命令得到这个信息。

如果你有process权限, 你能看见所有的线程,否则,你仅能看见你自己的线程。见7.20 KILL句法。如果你不使用FULL选项,那么每个查询只有头100字符被显示出来。

SHOW GRANTS FOR user列出对一个用户必须发出以重复授权的授权命令。

mysql> SHOW GRANTS FOR root@localhost;

+---------------------------------------------------------------------+

| Grants for root@localhost |

+---------------------------------------------------------------------+

| GRANT ALL PRIVILEGES ON *.* TO 'root''localhost' WITH GRANT OPTION |

+---------------------------------------------------------------------+

1

mongo中的group by

mongo中的group by

在mysql里面,我们偶尔会有这样的sql出现:
select userid,count(userid) as cnt from xxxxxtable group by userid;

这样的sql在mongo里怎么实现呢?其实也相对比较简单

<?php
$mongo = new Mongo();
$mongo->selectDB('xxx');//库
$collection = $mongo->selectCollection('表');

$field = array('userid'=>1);
$cnt = array('cnt'=>0);
$result = $collection->group($field,$cnt,"function(obj,pref){pref.cnt++;}");

打印出来的结果也很方便识别:

Array
(
[retval] => Array
(
[0] => Array
(
[userid] => 11111
[cnt] => 2
)
//省略
)

[count] => 21
[keys] => 11
[ok] => 1
)

果然轻轻松松啊

Mysql数据库索引查询优化的分享

Mysql数据库索引查询优化的分享

这是昨天SAE分享的一篇文章,开始的时候,我看了一遍,发现好象没有什么特别的内容,但再仔细看的时候,发现居然可以这样做。。。

问题描述:

我们要访问的表是一个非常大的表,四千万条记录,id是主键,program_id上建了索引。

执行一条SQL:

select * from program_access_log where program_id between 1 and 4000

这条SQL非常慢。我们原以为处理记录太多的原因,所以加了id限制,一次只读五十万条记录

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 4000

但是这条SQL仍然很慢,速度比上面一条几乎没有提升。Mysql处理50万条记录的表,条件字段还建了索引,这条语句应该是瞬间完成的。

问题分析:

这张表大约容量30G,数据库服务器内存16G,无法一次载入。就是这个造成了问题。

这条SQL有两个条件,ID一到五十万和Program_id一到四千,因为program_id范围小得多,mysql选择它做为主要索引。

先通过索引文件找出了所有program_id在1到4000范围里所有的id,这个过程非常快。

接下来要通过这些id找出表里的记录,由于这些id是离散的,所以mysql对这个表的访问不是顺序读取。

而这个表又非常大,无法一次装入内存,所以每访问一条记录mysql都要重新在磁盘上定位并把附近的记录都载入内存,大量的IO操作导致了速度的下降。

问题解决方案:

1. 以program_id为条件对表进行分区

2. 分表处理,每张表的大小不超过内存的大小

然而,服务器用的是mysql5.0,不支持分区,而且这个表是公共表,无法在不影响其它项目的条件下修改表的结构。所以我们采取了第三种办法:

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 15000000

现在program_id的范围远大于id的范围,id被当做主要索引进行查找,由于id是主键,所以查找的是连续50万条记录,速度和访问一个50万条记录的表基本一样

总结:

这是一个在千万笔记录表中由于使用了索引导致了数据查找变慢的问题,有一定的典型性和大家交流下!

-----------

看我标红的那一段,原来还能够这样做,以前真的没有注意过,也从来没有想过,先利用主键做一次过滤。这样效率会好很多啊

上述内容来自:http://ourmysql.com/archives/108?f=wb,该网站还有很多技巧值得一看。

Yii的又一个BUG?

Yii的又一个BUG?

先申明一下,这个可能不是BUG。只是算起来是实现的方式不一样而已。
场景:我有一个MYSQL数据库,但是现在容量越来越大,主要是因为其中有大字段,多个大字段,所以在查询的时候会特别特别慢。所以想到用mongo来存储一些查询用的结构。单条的时候,我还是准备采用MYSQL。当然其实单条用mongo也合适。不过因为迁移数据有点麻烦,所以还是先忍忍,一步一步来。

测试阶段:因为MYSQL to MONGO有点小麻烦,没有现成的工具。官方说有mongoimport,我看过了,确实OK,但是只支持一些基础的结构,比如:json,csv等。其他的则需要第三方工具。但我自己先在测试中,所以就直接写了个脚本,先将数据用AR取出来。然后插入到mongo中。结果发现,在排序的时候。。9999比10000还大。问了一下神仙 ,他说这应该是按字符串排序的方式来做的。

于是做了一个测试,写进了一个数字,果然就对了。。难道是yii的AR的BUG?想想这不太应该啊。于是我写了一个小的Demo:

$db = mysql_connect("localhost","root","123456");
mysql_select_db("feed");
$query = mysql_query("select id from feeds_group limit 1");
while($rs = mysql_fetch_array($query)){
$result = $rs;
echo "<pre>";
var_dump($result);
echo "</pre>";
}
echo "<hr />";
$dsn = 'mysql:host=localhost;dbname=feed';
$user = 'root';
$password = '123456';
$dbh = new PDO($dsn, $user, $password);
$sth = $dbh->prepare("select id from feeds_group limit 1");
$sth->execute();
$result = $sth->fetchAll();
echo "<pre>";
var_dump($result);
echo "</pre>";

打印出来一看:

array(2) {
[0]=>
string(1) "1"
["id"]=>
string(1) "1"
}

array(1) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
[0]=>
string(1) "1"
}
}

果然出来就是字符串了,最后只能自己在插到mongo的时候写了一个小函数,对于数值型字段做了转换,问题就这样解决了。

一不小心又把数据库折腾挂了

一不小心又把数据库折腾挂了。你妹啊。我只是移动了一点文件,居然就直接挂了,无法启动
再启动的时候,居然直接说。。。mysql启动文件找不到了。什么mysqld_safe之类都在。就是没有mysql。。。
当时心里就郁闷了。用repair修复的时候说。。。plugin表没权限 又说host表没权限 .
苦。最后在vampire的帮助下才搞定了。

苦。