薛亮的主页

  • 首页

  • 标签

  • 归档

  • 搜索

MySQL主从架构配置详解

发表于 2016-08-10 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

数据库基于 MySQL Server 5.6

无论是哪一种数据库,数据的安全都是至关重要的,因此熟练掌握数据库的安全备份功能,是作为开发人员,特别是后端开发人员的一项必备技能。MySQL 数据库内建的复制功能,可以帮助我们对数据进行异地备份,读写分离,在较大程度上避免数据丢失、数据库服务器压力过大甚至宕机带来的损失。

使用MySQL 主从架构一年多了,想起当年学习这些东西的时候,苦于完整的中文资料比较少,当时英文又不太好,遇到不少问题。刚好最近也有一段时间没更新博客了,心血来潮,决定翻译一下 MySQL 官网的英文文档,官网文档讲解的非常详细,可以帮助更多新手理解并快速入门。

第一次翻译这么大篇幅的英文技术文档,尽量采取逐句翻译,这样可以尽可能保持文档原意,但仍有很多需要修改的地方,恳请各位指正。

废话说多了,下面开始~~~

概述

MySQL的复制功能,使得数据可以从一台MySQL 数据库服务器(我们称之为主库,即 master),复制到另外一台或者多台MySQL 数据库服务器(我们称之为从库,即 slave)。在默认情况下,复制的过程是异步的,因此,从数据库服务器不需要一直连接到主数据库服务器接收更新。 这也意味着,更新可以在长距离连接,甚至在诸如拨号服务临时或者间歇性的情况下继续。MySQL的复制功能,可以复制所有数据库,或者需要复制的几个数据库,甚至数据库中需要复制的数据库表,这都依赖于你是如何配置的。

配置

配置主库

需要复制的主库必须开启二进制日志功能,并且创建一个唯一的服务器编号(server-id),之后,必须重启数据库。

由于二进制日志文件是主从复制的基础,所以,主库 必须 开启二进制日志功能。如果二进制日志功能没用使用 log-bin 选项开启,主从复制就无法进行。

可以将所有的从库作为一个组,组里的每一个从库都需要创建一个唯一的服务器编号(server-id),以便用这个编号在组里识别指定的从库,数据库服务器编号(server-id)必须是 1 至 232 − 1 之间的整数。具体使用哪些整数,完全由你自己决定,没有其他特殊规定。

要给数据库配置服务器编号(server-id)选项,需要停止MySQL 数据库,然后编辑 my.cnf 或者 my.ini 文件。在配置文件的 [mysqld] 这一节下,添加 log-bin 和 server-id 两个选项。如果它们已经存在,但是被注释掉了,就解注释,然后根据自己的需要进行修改。例如使用前缀为mysql-bin日志文件名,启用二进制日志功能,配置服务器编号为1,可以参考下面的示例:

1
2
3
[mysqld]
log-bin=mysql-bin
server-id=1

保存好上面的修改之后,重启数据库。

注意:

  • 如果没有配置 server-id 选项(或者将其设置为默认值0),主库将拒绝来自任何从库的连接请求。

  • 为了能在 InnoDB 存储引擎中使用事务时,达到最大可能的耐用性和一致性,需要在 my.cnf 文件中配置 innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 两个选项。

  • 不要在主库上配置 skip-networking 选项。如果主库的网络都被禁用了,从库就不能连接到主库,最终导致复制失败。

配置从库

前面在配置主库时,已经说过,必须给每个从库创建一个服务器编号,创建好之后,必须 重启数据库。

如果从库的服务器编号没有设置,或者设置的编号和主库冲突,就需要先停掉从库,然后编辑从库的配置文件的 [mysqld] 这一节,指定一个唯一的服务器编号,像下面这样:

1
2
[mysqld]
server-id=2

保存好修改之后,重启从库。
如果配置了多个从库,那么每一个从库都必须有一个唯一的 server-id 选项值(即每个从库的 server-id 值必须与主库以及除它本身以外的其他从库的 server-id 值不同)。

注意:
如果没有配置从库的 server-id 选项(或者配置它的值为默认值0),那么从库将拒绝连接到主库。

不需要为了主从复制而给从库开启二进制日志功能。如果给从库开启了二进制日志功能,由此产生的二进制日志文件可以作为备份数据,或者在数据库崩溃的时候,使用二进制日志文件恢复数据,也可以使用此开启了二进制日志功能的从库作为更复杂的主从架构的一部分。比如,可以将此从库作为其他从库的主库。

为从库创建用户

每个从库都使用数据库用户名和密码连接并登录到主库,所以在主库中必须有一个能让从库连接到此主库的 MySQL 账户。任何被赋予 REPLICATION SLAVE 权限的 MySQ L账户,都可以用作此连接操作。可以为每一个从库分配一个账户,也可以让所有的从库使用同一个账户,用来连接到主库。

虽然不需要为从库分配一个单独的账户去执行复制,但你应该知道的是,用来复制操作的用户名和密码都是明文存储在主库文件或表中的(相关链接:Section 17.2.2.2, “Slave Status Logs”)。因此,你可能想要创建一个隔离的、只能进行复制操作的账户,将对其他账户的损害减到最小。

使用 CREATE USER 语句创建新的 MySQL 账户。使用 GRANT 语句给这个账户赋予复制操作所必要的权限。若创建账户仅是为了达到复制的目的的话,那么这个账户只需要 REPLICATION SLAVE 。举个例子,创建一个新的账户 repl ,使其可以从 mydomain.com 域名下的任何主机连接到主库并执行复制,在主库上执行下面的语句:

1
2
CREATE USER 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.mydomain.com';

更多关于用户账户的操作语句,请查看 Section 13.7.1, “Account Management Statements”。

获取主库的二进制日志坐标

为了在接下来配置完从库,使其能从正确的位置开始执行复制操作,你需要知道主库当前的二进制日志坐标。

如果在主库上已经存储了一些数据,而且又需要在开始之前同步到从库上,那么就必须在主库上停止执行语句,接着,获取主库当前的日志坐标,并转存其数据。如果不使主库停止执行语句,将会导致转存的数据和数据库的状态信息不相符,最终导致从库数据不一致或者引起从库发生错误。

依照下面这几步来获取主库的二进制日志坐标:

  1. 使用命令行连接到主库以开始一个会话,清空所有表的缓存,并且通过执行 FLUSH TABLES WITH READ LOCK 阻止对数据库的写操作,即锁定对所有表的只读操作:
    1
    FLUSH TABLES WITH READ LOCK;

对于 InnoDB 存储引擎来说, FLUSH TABLES WITH READ LOCK 语句也会阻止 COMMIT 操作。

提醒:
不要退出刚才执行了 FLUSH TABLES 语句的会话。如果退出了这个会话,上面的锁表操作将被释放。

  1. 再打开一个新的会话,连接到主库,使用 SHOW MASTER STATUS 语句来确认当前二进制日志文件的名称和位置:
    1
    SHOW MASTER STATUS;

结果:

File Position Binlog_Do_DB Binlog_Ignore_DB
mysql-bin.000003 73 test manual,mysql

File 列显示了当前二进制日志文件的名字, Position 列显示了文件的位置。在上面这个例子中,二进制日志文件的名字是 mysql-bin.000003 ,位置是 73 。这些数据代表了从库将要(开始)处理来自主库的更新的坐标。记录下这些数据,稍后在配置从库时,将会使用到它们。

如果主库在事先没有开启二进制日志功能时已经在运行状态了,那么,通过执行 SHOW MASTER STATUS 语句,或者通过执行 mysqldump –master-data 命令,得到的结果中,二进制日志文件名和位置都将是空。若是那样的话,在从库上配置二进制日志名和位置时,就分别用空字符串('')和 数值 4 来代替。



到目前为止,我们已经获得了足够的信息,我们需要使用这些信息,配置从库,使从库开始从正确的位置读取来自主库的二进制日志,开始进行复制。

如果你有一些数据,需要在从库开始复制之前同步到从库,那么,保持之前开启的会话不要关闭,这样才能保持之前开启的数据库锁不被释放。接着,查看 Section 17.1.1.5, “Creating a Data Snapshot Using mysqldump” 或者 Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files” 。它们将会告诉你如何防止任何进一步的更改,以便于将已经存在于主库的数据同步到从库。

如果你正在建立一个全新的主从复制组,你可以退出第一个会话,以便释放对数据库的读锁定。

使用新的主、从库配置复制

使用新的主、从库配置数据库复制是最简单、最直接的方式。

如果你正在设置新的服务器,但是有一些从其他的务器转存的数据库,并且你想加载到你的复制配置新中,同样可以使用本节介绍的方法。通过将数据加载到新的主库中,数据将会被自动复制到从库中。

依照下面这几步,来在新的主、从库之间配置复制功能:

  1. 通过一些必要的配置属性文件,配置主库。参考:配置主库
  2. 启动主库。
  3. 设置一个用户。参考:为从库创建用户。
  4. 获取主库的状态信息。参考:获取主库的二进制日志坐标。
  5. 在主库上释放读锁:

    1
    UNLOCK TABLES;
  6. 在从库上编辑 MySQL 配置文件。 参考:配置从库。

  7. 启动从库。
  8. 执行 CHANGE MASTER TO 语句来设置主库的信息。参考:为从库配置主库的信息。

在每一台从库上,都完成上面这几步操作。

因为使用的是新的数据库,没有数据或者配置信息需要替换,因此你不需要复制或者导入任何其他信息。

如果你需要使用来自于其他数据库服务器上数据配置新的复制环境,你可能需要在新的主库上导入这些转存的数据。由此对主库产生的更新将会被自动同步到从库:

1
mysql -h master < fulldb.dump

使用已有的数据配置复制环境

当使用已有的数据配置复制环境时,你可能需要做出一个决定,如何在启动复制服务之前,让从库以最优方式获取到主库的数据。
下面这几步基本操作将会引导你,使用已有的数据配置复制环境:

  1. 在 MySQL 主库运行的情况下,创建一个用户,以便从库在复制的时候可以连接到主库。参考:为从库创建用户。

  2. 如果你还没有在主库上配置 server-id 选项,或者还没有开启二进制日志功能,你需要停止主库,然后配置它们。参考:配置主库。
    在配置主库的过程中,如果需要停止(重启)主库服务,你可以利用主库服务停止的这段时间,创建一个主库的快照。但别忘了,你需要在停止主库服务、更新配置信息,创建快照之前,获得主库的状态信息(参考:获取主库的二进制日志坐标)。关于如何使用原始数据创建数据库快照,你可以参考这里:Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files”。

  3. 如果主库信息已经正确配置好了,那么就可以获取它的状态信息(参考:获取主库的二进制日志坐标),接着,使用 MySQL 自带的 mysqldump 工具创建一个数据库快照(参考:Section 17.1.1.5, “Creating a Data Snapshot Using mysqldump”),也可以参考 Section 17.1.1.6, “Creating a Data Snapshot Using Raw Data Files” 直接创建主库的原始数据文件的快照。

  4. 更新从库的配置信息。参考:配置从库。
  5. 这一步的操作,取决于你在主库上是如何创建的数据的快照的。
    若你是使用的 mysqldump 创建的快照:
  • 使用 --skip-slave-start 选项启动从库,以便不让主从复制开始。
  • 像下面这样,导入转存的数据文件:
    1
    mysql < fulldb.dump

若你是使用第二种方案,即直接创建原始数据文件的快照的方式:

  • 将数据文件解压到从库的数据(data)目录下:

    1
    tar xvf dbdump.tar
    你可能需要设置这些文件的权限和所有者,以便在从库可以获取到这些数据文件,并且可以对其进行更新。
    
  • 使用 --skip-slave-start 选项启动从库,以便不让主从复制开始。

  1. 将主库的二进制日志坐标信息配置到从库。这一步用来指定从库需要从主库的哪一个二进制日志文件,以及从这个文件的什么位置开始复制。当然,也需要在从库上配置连接主库时使用的凭证和主库的 IP 或者 域名。更多关于 CHANGE MASTER TO 语句的所需的必须参数等信息,请参考:为从库配置主库的信息。
  2. 启动从库:

    1
    START SLAVE;

执行完上面这几步,从库就会连接到主库,主库的任何更新操作,都将被发送到从库,从库会在已有的快照数据的基础上,同步执行这些更新。

如果你忘记了设置主库的 server-id 选项信息,从库将无法连接到主库。
如果你忘记了设置从库的 server-id 选项信息,在从库的错误日志中,将出现以下错误信息:

Warning: You should set server-id to a non-0 value if master_host
is set; we will force server id to 2, but this MySQL server will
not act as a slave.

同样,如果从库由于其他任何原因导致不能执行复制,你可以在错误日志文件中得到相关的错误信息。

从库通过使用存储在主库信息仓库中的信息,保持跟踪它已经执行了多少主库产生的二进制日志。通过 --master-info-repository 选项,可以将仓库信息设置在文件的表单里,或者在一个表中。当配置信息为 --master-info-repository=FILE 时,你可以在从库的数据(data)目录下发现两个文件,名字分别是 master.info 和 relay-log.info 。配置信息为 --master-info-repository=TABLE 时,信息将会被保存在 mysql 数据库的 master_slave_info 表中。无论如何,不要删除或者编辑上面提到的文件和表里的数据,除非你清楚的知道你在干什么,并且充分理解这么做代表的含义。即便如此,也应该优先使用 CHANGE MASTER TO 语句去修改复制参数。从库可以使用语句中指定的值去自动更新状态信息文件。更多相关信息请参考:Section 17.2.2, “Replication Relay and Status Logs”。

注意:
主库信息仓库的内容会覆盖一些在命令行或者 my.cnf 文件中设置的选项。详细信息请参考:Section 17.1.4, “Replication and Binary Logging Options and Variables”。

一份主库的快照,可以被多个从库来使用。如果需要额外再配置一些从库,可以使用相同的主库快照,像之前介绍如何配置已有从库时描述的那样,配置这些额外增加的从库。

为从库配置主库的信息

你必须告诉告诉从库一些必要信息,以便从库能够连接到主库进行复制。为了做到这一点,在从库上执行下面的语句,根据你的系统上实际的值,替换语句中相应的选项值:

1
CHANGE MASTER TO MASTER_HOST='master_host_name', MASTER_USER='replication_user_name', MASTER_PASSWORD='replication_password', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position;

注意:
复制不能使用 Unix 套接字文件(socket file)。你必须确保能够使用 TCP/IP 协议连接到主库。

CHANGE MASTER TO 语句也有一些其他参数可供配置。例如,可以通过使用此语句的其他选项,决定是否使用 SSL 协议,以便达到安全的复制。
关于此语句的完整的选项,以及选项值允许的最大长度等信息,请参考:Section 13.4.2.1, “CHANGE MASTER TO Syntax”。

MySQL中字符串、日期时间等常用函数总结

发表于 2016-07-31 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

数据库基于 MySQL Server 5.6

由于数据库自带函数的效率问题,对于海量数据的处理时,将加大数据库压力,使之成为系统的瓶颈。但对于大部分的初创等小型公司来说,数据并不多时,数据库函数并不能成为系统瓶颈,这时使用数据库自带的函数将给我们带来很大方便。所以这两天就梳理了一些MySQL中字符串、日期和时间等比较常用的函数,和各位分享。

控制流程函数

CASE

  • CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result …] [ELSE result] END
  • CASE WHEN [condition] THEN result [WHEN [condition] THEN result …] [ELSE result] END

这里有两个方案,第一个方案对 value 判定,每个 WHEN compare_value THEN result 或 ELSE 是一个分支,若分支中compare_value 与 value 相等,则返回对应的 THEN 后的 result,若所有 WHEN 后的 compare_value 都不与 value 想的呢过,则返回 ELSE 后的 result,若没有 ELSE,则返回 NULL。
示例:

1
SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;

结果

one

第二个方案对每个 WHEN 后的表达式进行判定,若判定结果为 true,则返回对应的 THEN 后的结果,若所有 WHEN 后的判定结果均为 false ,则返回 ELSE 后的 result,若没有 ELSE,则返回 NULL。
示例:

1
SELECT CASE WHEN 1 > 0 THEN 'true' ELSE 'false' END;

结果

true

IF

  • IF(expr1, expr2, expr3)

IF 函数类似与 Java 或其他语言中的三元运算符,即对 expr1 进行判定,若结果为 true(expr1 <> 0 and expr1 <> NULL),则返回 expr2,否则,返回expr3。
示例1:

1
SELECT IF(1 > 2, 2, 3);

结果:

3

示例2:

1
SELECT IF(1 < 2, 'yes', 'no');

结果:

yes

示例3:

1
SELECT IF(STRCMP('test', 'test1'), 'no', 'yes');

结果:

no

IFNULL

  • IFNULL(expr1, expr2)

IFNULL 语句与上面的 IF() 函数有点类似对 expr1 进行判定,若 expr1 不为空,则返回 expr1,否则返回 expr2。
示例1:

1
SELECT IFNULL(1, 0);

结果:

1

示例2:

1
SELECT IFNULL(NULL, 10);

结果:

10

示例3:

1
SELECT IFNULL(1/0, 'yes');

结果:

yes

NULLIF

  • NULLIF(expr1, expr2)

若 expr1 与 expr2 相等,则返回 NULL,否则返回 expr1。和 CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END 效果相同。
示例1:

1
SELECT NULLIF(1, 1);

结果:

NULL

示例2:

1
SELECT NULLIF(1, 2);

结果:

1

字符串函数

字符串比较函数

LIKE

  • expr LIKE pat [ESCAPE ‘escape_char’]

模式匹配,使用SQL简单正规表达式比较。返回1 (TRUE) 或 0 (FALSE)。 若 expr 或 pat 中任何一个为 NULL,则结果为 NULL。
模式不需要为文字字符串,可以被指定为一个字符串表达式或表列。
在模式中可以同 LIKE 一起使用以下两种通配符:
字符|说明
—| —————————-
%|匹配任何数目的字符,甚至包括零个字符
_|只能匹配一个字符

示例1:

1
SELECT 'David!' LIKE 'David_';

结果:

1
示例2:

1
SELECT 'David!' LIKE '%D%v%';

结果:

1

若要将通配符视为普通字符,以便在字符串中匹配通配符,可将转义符(默认为\)置于此通配符前面即可。
示例1:

1
SELECT 'David!' LIKE 'David\_';

结果:

0

示例2:

1
SELECT 'David_' LIKE 'David\_';

结果:

1

要指定一个不同的转义字符,可使用 ESCAPE 语句。
示例:

1
SELECT 'David_' LIKE 'David|_' ESCAPE '|';

结果:

1

转义序列可以为空,也可以是一个字符的长度。
字符串比较不区分大小写,除非其中的一个比较对象是大小写敏感的(使用区分大小写敏感的字符集或者是一个二进制字符串)。
示例1:

1
SELECT 'abc' LIKE 'ABC';

结果:

1

示例2:

1
SELECT 'abc' LIKE _latin1 'ABC' COLLATE latin1_general_cs;

结果:

0

示例3:

1
SELECT 'abc' LIKE _latin1 'ABC' COLLATE latin1_bin;

结果:

0

示例4:

1
SELECT 'abc' LIKE BINARY 'ABC';

结果:

0

作为对标准 SQL 的扩展,MySQL 允许 LIKE 函数作用在数字表达式上。
示例:

1
SELECT 10 LIKE '1%';

结果:

1

NOT LIKE

  • expr NOT LIKE pat [ESCAPE ‘escape_char’]

和 NOT (expr LIKE pat [ESCAPE ‘escape_char’]) 效果相同。

正则表达式函数

REGEXP

  • expr REGEXP pat
  • expr RLIKE pat

用给定的正则表达式 pat 匹配字符串 expr,如果匹配成功,则返回 1。否则返回 0。正则表达式 pat 和字符串 expr 二者任意一个为空时,将返回 NULL。RLIKE 是 REGEXP 的同义词, 是为了兼容 mSQL。
正则表达式 pat 不需要为字符串。例如,可以被指定为一个字符串表达式或表列。
REGEXP 是不区分大小写的,除非跟二进制字符串一起使用。
示例1:

1
SELECT 'Monty!' REGEXP '.*';

结果:

1

示例2:

1
SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';

结果:

1

示例3:

1
SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';

结果:

1 0

示例5:

1
SELECT 'a' REGEXP '^[a-d]';

结果:

1

NOT REGEXP

  • expr NOT REGEXP pat
  • expr NOT RLIKE pat

相当于 NOT (expr REGEXP pat)。

数值函数

数学函数

TRUNCATE

  • TRUNCATE (X, D)

返回被舍去至小数点后 D 位的数字 X。若 D 的值为 0, 则结果不带有小数点或不带有小数部分。可以将 D 设为负数,若要截去(归零) X小数点左起第 D 位(含)开始后面所有低位的值。

日期和时间函数

ADDDATE

  • ADDDATE(date, INTERVAL expr unit)
  • ADDDATE(expr, days)

当被第二个参数的 INTERVAL 格式激活后, ADDDATE() 的用法和 DATE_ADD() 的相同。相关函数 SUBDATE() 的用法和 DATE_SUB() 相同。对于 INTERVAL 参数上的信息 ,请参见关于 DATE_ADD() 的论述。
示例1:

1
SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY);

结果:

2008-02-02

示例2:

1
SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY);

结果:

2008-02-02

ADDTIME

  • ADDTIME(expr1, expr2)

ADDTIME() 将 expr2 添加至 expr 然后返回结果。expr 是一个时间或时间日期表达式,而 expr2 是一个时间表达式。

CURDATE

  • CURDATE()

将当前日期按照 ‘YYYY-MM-DD’ 或 YYYYMMDD 格式的值返回,具体格式根据函数用在字符串或是数字语境中而定。
示例1:

1
SELECT CURDATE();

结果:

2016-07-29

示例2:

1
SELECT CURDATE() + 0;

结果:

20060729

CURRENT_DATE

  • CURRENT_DATE
  • CURRENT_DATE()

CURRENT_DATE 和 CURRENT_DATE() 的用法与 CURDATE() 相同。

CURTIME

  • CURTIME([fsp])

将当前时间以 ‘HH:MM:SS’ 或 HHMMSS 的格式返回,具体格式根据函数用在字符串或是数字语境中而定。该值表示当前时区的时间。从 MySQL 5.6.4 开始,fsp 参数用来指定返回值中小数位的长度,该参数的取值范围 0 - 6。在 MySQL5.6.4 之前,给CURTIME() 函数传递任何参数都会被忽略。
示例1:

1
SELECT CURTIME();

结果:

16:38:39

示例2:

1
SELECT CURTIME();

结果:

163927

CURRENT_TIME

  • CURRENT_TIME
  • CURRENT_TIME([fsp])

CURRENT_TIME 和 CURRENT_TIME() 的用法与 CURTIME() 函数相同。

NOW

  • NOW([fsp])

返回当前日期和时间值,其格式为 ‘YYYY-MM-DD HH:MM:SS’ 或YYYYMMDDHHMMSS, 具体格式取决于该函数是否用在字符串中或数字语境中。该值表示当前时区的时间。从 MySQL 5.6.4 开始,fsp 参数用来指定返回值中小数位的长度,该参数的取值范围 0 - 6。在 MySQL5.6.4 之前,给 NOW() 函数传递任何参数都会被忽略。
示例1:

1
SELECT NOW();

结果:

2016-07-29 16:49:28

示例2:

1
SELECT NOW() + 0;

结果:

20160729165026

NOW() 返回一个固定时间,该时间指示了该开始执行的时间(在存储函数或者触发器中,NOW() 函数返回存储函数或者触发器开始执行的时间)。这同 SYSDATE() 的运行有所不同,SYSDATE() 函数返回它自身执行的时间。
示例1:

1
SELECT NOW(), SLEEP(2), NOW();

结果:

NOW() SLEEP(2) NOW()
2016-07-29 17:16:40 0 2016-07-29 17:16:40

示例2:

1
SELECT SYSDATE(), SLEEP(2), SYSDATE();

结果:

SYSDATE() SLEEP(2) SYSDATE()
2016-07-29 17:52:24 0 2016-07-29 17:52:26

CURRENT_TIMESTAMP

  • CURRENT_TIMESTAMP
  • CURRENT_TIMESTAMP([fsp])

CURRENT_TIMESTAMP 和 CURRENT_TIMESTAMP() 的用法与 NOW() 函数相同。

DATE

  • DATE(expr)

提取日期或时间日期表达式 expr 中的日期部分,若没有提取到,则返回 NULL。
示例:

1
SELECT DATE('2016-12-31 01:02:03');

结果:

2016-12-31

DATEDIFF

  • DATEDIFF(expr1, expr2)

返回起始时间 expr1 和结束时间 expr2 之间的天数(即表达式 expr1 - expr2 的值)。expr1 和 expr2 为日期或 date-and-time 表达式。计算中只用到这些值的日期部分。
示例1:

1
SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30');

结果:

1

示例2:

1
SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31');

结果:

-31

DATE_ADD, DATE_SUB

  • DATE_ADD(date, INTERVAL expr unit)
  • DATE_SUB(date, INTERVAL expr unit)

这两个函数执行日期运算。参数 date 是一个 DATETIME 或 DATE 值,用来指定起始日期。 expr 是一个表达式,用来指定从起始日期(即参数 date)添加或减去的日期间隔值。expr 是一个字符串;对于负值的日期间隔,它可以以一个 “-”开头。 type 为关键词,它指示了表达式被解释的方式。
关键词 INTERVA 及 unit 分类符均不区分大小写。
下表展示了unit 和 expr 参数的关系:
unit 值 | 期望的 expr 值
——————- | ————-
MICROSECOND | MICROSECONDS
SECOND | SECONDS
MINUTE | MINUTES
HOUR | HOURS
DAY | DAYS
WEEK | WEEKS
MONTH | MONTHS
QUARTER | QUARTERS
YEAR | YEARS
SECOND_MICROSECOND| ‘SECONDS.MICROSECONDS’
MINUTE_MICROSECOND| ‘MINUTES:SECONDS.MICROSECONDS’
MINUTE_SECOND | ‘MINUTES:SECONDS’
HOUR_MICROSECOND | ‘HOURS:MINUTES:SECONDS.MICROSECONDS’
HOUR_SECOND | ‘HOURS:MINUTES:SECONDS’
HOUR_MINUTE | ‘HOURS:MINUTES’
DAY_MICROSECOND | ‘DAYS HOURS:MINUTES:SECONDS.MICROSECONDS’
DAY_SECOND | ‘DAYS HOURS:MINUTES:SECONDS’
DAY_MINUTE | ‘DAYS HOURS:MINUTES’
DAY_HOUR | ‘DAYS HOURS’
YEAR_MONTH | ‘YEARS-MONTHS’
返回值取决于传递的参数。
示例1:

1
SELECT DATE_ADD('2010-12-31 23:59:59', INTERVAL 1 DAY);

结果:

2011-01-01 23:59:59

示例2:

1
SELECT DATE_ADD('2100-12-31 23:59:59', INTERVAL '1:1' MINUTE_SECOND);

结果:

2101-01-01 00:01:00

示例3:

1
SELECT DATE_SUB('2005-01-01 00:00:00', INTERVAL '1 1:1:1' DAY_SECOND);

结果:

2004-12-30 22:58:59

DATE_FORMAT

  • DATE_FORMAT(date, format)

根据 format 字符串安排 date 值的格式。
说明符 | 说明
—– | —-
%a | 工作日的缩写名称 (Sun..Sat)
%b | 月份的缩写名称 (Jan..Dec)
%c | 月份,数字形式(0..12)
%D | 带有英语后缀的该月日期 (0th,1st,2nd,3rd,···)
%d | 该月日期,数字形式 (00..31)
%e | 该月日期,数字形式(0..31)
%f | 微秒 (000000..999999)
%H | 小时(00..23)
%h | 小时(01..12)
%I | 小时 (01..12)
%i | 分钟,数字形式 (00..59)
%j | 一年中的天数 (001..366)
%k | 小时 (0..23)
%l | 小时 (1..12)
%M | 月份名称 (January..December)
%m | 月份,数字形式 (00..12)
%p | 上午(AM)或下午( PM)
%r | 时间,12小时制 (小时hh:分钟mm:秒数ss 后加 AM或PM)
%S | 秒 (00..59)
%s | 秒 (00..59)
%T | 时间,24小时制 (小时hh:分钟mm:秒数ss)
%U | 周 (00..53), 其中周日为每周的第一天
%u | 周 (00..53), 其中周一为每周的第一天
%V | 周 (01..53), 其中周日为每周的第一天;和 %X 同时使用
%v | 周 (01..53), 其中周一为每周的第一天;和 %x 同时使用
%W | 工作日名称 (周日..周六)
%w | 一周中的每日 (0=周日..6=周六)
%X | 该周的年份,其中周日为每周的第一天;数字形式,4位数;和 %V 同时使用
%x | 该周的年份,其中周一为每周的第一天,数字形式,4位数;和 %v 同时使用
%Y | 年份,数字形式,4位数
%y | 年份,数字形式 (2位数)
%% | % 字符
示例1:

1
SELECT DATE_FORMAT('1900-10-04 22:23:00', '%D %y %a %d %m %b %j');

结果:

4th 00 Thu 04 10 Oct 277

示例2:

1
SELECT DATE_FORMAT('1999-01-01', '%X %V');

结果:

1998 52

Linux下,Nginx的安装、升级及动态添加模块

发表于 2016-06-17 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64

安装

第一步 下载并解压Nginx压缩包

从Nginx官网下载Nginx,或者在Linux上执行wget http://nginx.org/download/nginx-1.10.1.tar.gz命令直接下载
解压nginx-1.10.1.tar.gz文件:

1
tar zxvf nginx-1.10.1.tar.gz

第二步 配置

1
2
cd nginx-1.10.1
./configure --prefix=/usr/local/nginx

注意:
① 如果之前没有安装C compiler(C 编译器),这一步将报如下错误信息:

xueliang@dev:~/download/nginx-1.10.1\$ ./configure –prefix=/usr/local/nginx
checking for OS

  • Linux 4.2.0-27-generic x86_64
    checking for C compiler … not found

./configure: error: C compiler cc is not found

xueliang@dev:~/download/nginx-1.10.1\$

可以参考这篇文章安装C compiler,然后继续下面的操作

② 如果之前没有安装PCRE,这一步将报如下错误信息:

checking for PCRE library … not found
checking for PCRE library in /usr/local/ … not found
checking for PCRE library in /usr/include/pcre/ … not found
checking for PCRE library in /usr/pkg/ … not found
checking for PCRE library in /opt/local/ … not found

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using –without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using –with-pcre= option.

xueliang@dev:~/download/nginx-1.10.1\$

可以参考这篇文章安装PCRE,然后继续下面的操作

③ 如果之前没有安装zlib,这一步将报如下错误信息:

checking for md5 in system md library … not found
checking for md5 in system md5 library … not found
checking for md5 in system OpenSSL crypto library … not found
checking for sha1 in system md library … not found
checking for sha1 in system OpenSSL crypto library … not found
checking for zlib library … not found

./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using –without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using –with-zlib= option.

xueliang@dev:~/download/nginx-1.10.1\$

可以参考这篇文章安装zlib,然后继续下面的操作

也可以跳过此步,执行默认安装,--prefix的默认值为/usr/local/nginx,Nginx官网对此有说明:Building nginx from Sources

第三步 编译

1
make

第四步 完成安装

1
sudo make install

平滑升级

当需要对正在运行的Nginx进行升级时,可以在不停止Nginx的情况下,使用新版本或者重编译的可执行程序替换旧版本的可执行程序,这里我们从nginx-1.10.1升级到nginx-1.11.1。

第一步 备份旧版本

因为Nginx的升级,实质只是用新版本的可执行文件,替换旧版本的可执行程序,所以,对于备份,既可以只备份旧版本可执行文件,也可以打包备份整个旧版本安装目录,参考命令分别如下:
只备份旧版本可执行文件

1
sudo cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak

打包备份整个旧版本安装目录

1
sudo tar -cvf /usr/local/nginx.bak /usr/local/nginx

第二步 下载新版本并解压Nginx压缩包

对于新版本Nginx压缩包的下载和解压,可以参考本文关于Nginx的安装部分的第一、二步。

第三步 使用旧版本配置参数,配置并编译新版本Nginx

因为只是对Nginx进行升级,并不涉及配置参数的修改,所以,我们一般使用和旧版本相同的配置(当然你也可以使用全新的配置信息),来编译新版本的Nginx,使用如下命令查看旧版本配置信息:

1
/usr/local/nginx/sbin/nginx -V

可以得到结果如下:

xueliang@dev:~/download/nginx-1.11.1\$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.1
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
configure arguments: –prefix=/usr/local/nginx
xueliang@dev:~/download/nginx-1.11.1\$

其中 [configure arguments: –prefix=/usr/local/nginx] 这一行即为旧版本Nginx配置信息,这里可以看出,旧版本只是指定了安装路径,使用[configure arguments:]后面的参数信息,对新版本Nginx作相同配置,然后进行编译:

1
./configure --prefix=/usr/local/nginx

第四步 编译新版本Nginx可执行程序

1
make

第五步 用新版本Nginx可执行程序覆盖旧版本可执行程序

在上一步的基础上,执行一下命令即可:

1
sudo cp objs/nginx /usr/local/nginx/sbin/nginx

执行这条命令,可能会报以下异常,提示文件被占用:

xueliang@dev:~/download/nginx-1.11.1\$ sudo cp objs/nginx /usr/local/nginx/sbin/nginx
cp: cannot create regular file ‘/usr/local/nginx/sbin/nginx’: Text file busy
xueliang@dev:~/download/nginx-1.11.1\$

可以使用以下命令进行强制覆盖:

1
sudo cp -rfp objs/nginx /usr/local/nginx/sbin/nginx

第六步 启动新版本Nginx主进程

发送 USR2信号给旧版本主进程号:

1
kill -USR2 旧版本的Nginx主进程号

旧版本Nginx主进程接收到-USR2信号,将重命名它的.pid文件为.oldbin,然后执行新版本的Nginx可执行程序,依次启动新版本的主进程和工作进程:

PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1380 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1164 kqread nginx: worker process (nginx)

第七步 从容关闭旧版本的工作进程

此时,新、旧版本的Nginx实例会同时运行,共同处理请求,如果此时给旧版本主进程发送WINCH 信号,旧版本主进程将会给它的工作进程发送消息,请求它们从容关闭,此后,旧版本的工作进程开始逐步退出:

PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33135 33126 nobody 0.0 1380 kqread nginx: worker process is shutting down (nginx)
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

从容关闭旧版本的工作进程命令:

1
kill -WINCH 旧版本的Nginx主进程号

第八步 从容关闭旧版本的主进程,完成Nginx的升级

经过一段时间后,旧的工作进程(work process)处理完了所有已连接的请求后退出,仅由新版本的工作进程来处理新的请求了:

PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

应该注意的是,此时,旧版本的主进程还尚未关闭它监听的套接字,如果有需要,你仍可以恢复旧版本工作进程。如果由于某些原因,新版本的可执行文件运行情况不理想,下面有几种方案可供参考:

  • 给旧版本主进程发送 HUP 信号。旧版本主进程将在不重新读取配置信息的情况下,重新开启工作进程。然后,通过给新版本主进程发送 QUIT 信号,所有新版本的进程将会从容关闭。
  • 给新版本主进程发送 TERM 信号。然后,他将会给它的工作进程发送消息,要求它们立即退出,紧接着,这些工作进程就会立即退出。(如果因为某些原因,新版本进程没有退出,应该给新版本主进程发送 KILL 信号,强制新版本主进程退出。)新版本主进程退出的同时,旧版本主进程将会自动启动它的工作进程。
    新版本主进程退出后,旧版本主进程将会移除名字以.oldbin 结尾的文件,恢复为它的 .pid 文件。

如果升级成功,应该给旧版本主进程发送 QUIT 信号:

1
kill -QUIT 旧版本的Nginx主进程号

使其退出,只保留新版本进程:

PID PPID USER %CPU VSZ WCHAN COMMAND
36264 33126 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36266 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)
36267 36264 nobody 0.0 1364 kqread nginx: worker process (nginx)

添加模块

刚接触Nginx时,只知道Nginx的功能是分模块的,并不清楚有些模块默认是不参与到构建中去的,比如ngx_http_ssl_module模块,是用来支持https协议的,默认情况下是没有构建到Nginx中的。
随着业务不断扩展,如果需要Nginx支持某些模块,而这些模块默认不在Nginx的构建计划中,构建Nginx时,又没有指定加入这些模块,该怎么办呢?是否能够给已经运行的Nginx动态添加这些模块呢?答案是肯定的!
给运行中的Nginx动态添加模块的方案,与上面提到的平滑升级Nginx的方案很类似。下面我们来看一下如何给运行中的Nginx添加 ngx_http_ssl_module 模块。

第一步 查看运行中的Nginx版本,并下载、解压对应版本的压缩包

查看Nginx版本:

1
/usr/local/nginx/sbin/nginx -v

结果:

xueliang@dev:~\$ /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.11.1
xueliang@dev:~\$

或者:

1
/usr/local/nginx/sbin/nginx -V

结果:

xueliang@dev:~\$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.11.1
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
configure arguments: –prefix=/usr/local/nginx
xueliang@dev:~\$

这里可以看出,正在运行的Nginx版本为1.11.1,参照安装Nginx部分,下载并解压对应版本的Nginx

第二步 编译Nginx,同时加入需要模块配置

参考平滑升级的第三步,查看运行中的Nginx的配置参数,并在最后追加-with-http_ssl_module。
如:原配置信息为 --prefix=/usr/local/nginx,则新配置信息为 --prefix=/usr/local/nginx --with-http_ssl_module,配置Nginx执行的命令如下:

1
./configure --prefix=/usr/local/nginx --with-http_ssl_module

第三步 平滑重启Nginx,完成动态模块添加

这一步可以参考平滑升级的第四至八步

Linux下安装zlib

发表于 2016-06-17 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64,即Ubuntu系统的服务器版本,基本适用于桌面版

安装

第一步 下载并解压zlib压缩包

打开zlib官网,找到下载链接,右键复制地址:
enter image description here

在Linux中使用wget命令下载,执行如下命令开始下载:

1
wget http://zlib.net/zlib-1.2.8.tar.gz

解压:

1
tar zxvf zlib-1.2.8.tar.gz

第二步 开始安装

安装过程比较简单,进入zlib的解压目录,依次执行下面几条命令即可:

配置:

1
./configure

如果之前没有安装gcc(C 编译器),这一步将报如下错误信息::

xueliang@dev:~/download/zlib-1.2.8\$ ./configure
Checking for gcc…
Compiler error reporting is too harsh for ./configure (perhaps remove -Werror).
** ./configure aborting.
xueliang@dev:~/download/zlib-1.2.8\$

可以参考这篇文章安装gcc(C 编译器),然后继续下面的操作

编译:

1
make

如果之前没有安装make命令,这一步将报如下错误信息:

xueliang@dev:~/download/zlib-1.2.8\$ make
The program ‘make’ is currently not installed. You can install it by typing:
sudo apt-get install make
xueliang@dev:~/download/zlib-1.2.8\$

可以参考这篇文章安装make命令,然后继续下面的操作

对编译结果进行测试:

1
make test

如果编译无误,会得到如下信息:

xueliang@dev:~/download/zlib-1.2.8\$ make test
hello world
zlib version 1.2.8 = 0x1280, compile flags = 0xa9
uncompress(): hello, hello!
gzread(): hello, hello!
gzgets() after gzseek: hello!
inflate(): hello, hello!
large_inflate(): OK
after inflateSync(): hello, hello!
inflate with dictionary: hello, hello!
zlib test OK
hello world
zlib version 1.2.8 = 0x1280, compile flags = 0xa9
uncompress(): hello, hello!
gzread(): hello, hello!
gzgets() after gzseek: hello!
inflate(): hello, hello!
large_inflate(): OK
after inflateSync(): hello, hello!
inflate with dictionary: hello, hello!
zlib shared test OK
hello world
zlib version 1.2.8 = 0x1280, compile flags = 0xa9
uncompress(): hello, hello!
gzread(): hello, hello!
gzgets() after gzseek: hello!
inflate(): hello, hello!
large_inflate(): OK
after inflateSync(): hello, hello!
inflate with dictionary: hello, hello!
zlib 64-bit test OK
xueliang@dev:~/download/zlib-1.2.8\$

如果通过测试,就可以开始安装了,执行如下命令完成zlib的安装:

1
sudo make install

卸载

在zlib的解压目录下,一条命令搞定:

1
sudo make uninstall

完成卸载:

xueliang@dev:~/download/zlib-1.2.8\$ sudo make uninstall
cd /usr/local/include && rm -f zlib.h zconf.h
cd /usr/local/lib && rm -f libz.a; \
if test -n “libz.so.1.2.8” -a -f libz.so.1.2.8; then \
rm -f libz.so.1.2.8 libz.so libz.so.1; \
fi
cd /usr/local/share/man/man3 && rm -f zlib.3
cd /usr/local/lib/pkgconfig && rm -f zlib.pc
xueliang@dev:~/download/zlib-1.2.8\$

Linux下安装C++ compiler

发表于 2016-06-16 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64,即Ubuntu系统的服务器版本,基本适用于桌面版

C++ compiler的安装同样很简单,使用APT工具安装,执行如下命令即可:

1
sudo apt-get install g++

对,你没有看错,是g++,而不是c++…Google了一把,说是C++ 编译器在软件仓库中改名了…


2016年09月25日更新:CentOS 7 安装C++ compiler

CentOS 7使用 yum 安装C++ compiler:

1
sudo yum install gcc-c++

Linux下安装make命令

发表于 2016-06-16 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64,即Ubuntu系统的服务器版本,基本适用于桌面版

make命令的安装很简单,使用APT工具安装,执行如下命令即可:

1
sudo apt-get install make

Linux下PCRE的安装与卸载

发表于 2016-06-16 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64,即Ubuntu系统的服务器版本,基本适用于桌面版

安装

第一步 到PCRE官网下载PCRE的压缩包,并解压

PCRE官网首页找到下载页面链接:
图片加载中...

这里我们选择PCRE1的最新版(8.39),右键复制链接地址:
图片加载中...

在Linux中使用wget命令下载,执行如下命令开始下载:

1
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.39.tar.gz

解压:

1
tar zxvf pcre-8.39.tar.gz

第二步 进行安装

进入PCRE的解压目录,开始安装,安装过程比较简单,依次执行下面几条命令即可:

配置:

1
./configure

注意:
(1) 如果之前没有安装C compiler(C 编译器),这一步将报如下错误信息:

configure: error: in `/home/xueliang/download/pcre-8.39’:
configure: error: no acceptable C compiler found in \$PATH
See `config.log’ for more details
xueliang@dev:~/download/pcre-8.39$

可以参考这篇文章安装C compiler,然后继续下面的操作

(2) 如果之前没有安装C++ compiler(C++ 编译器),这一步将报如下错误信息:

configure: error: You need a C++ compiler for C++ support.
xueliang@dev:~/download/pcre-8.39\$

可以参考这篇文章安装C++ compiler,然后继续下面的操作

编译:

1
make

如果之前没有安装make命令,这一步将报如下错误信息:

xueliang@dev:~/download\$ make
The program ‘make’ is currently not installed. You can install it by typing:
sudo apt-get install make
xueliang@dev:~/download\$

可以参考这篇文章安装make命令,然后继续下面的操作

对编译结果进行测试:

1
make test

如果编译无误,会得到如下信息:

Testsuite summary for PCRE 8.39

TOTAL: 5

PASS: 5

SKIP: 0

XFAIL: 0

FAIL: 0

XPASS: 0

ERROR: 0

如果通过测试,就可以开始安装了,执行如下命令完成PCRE的安装:

1
sudo make install

卸载

在PCRE的解压目录下,一条命令搞定:

1
sudo make uninstall

完成卸载:

xueliang@dev:~/download/pcre-8.39\$ sudo make uninstall
[sudo] password for xueliang:
( cd ‘/usr/local/bin’ && rm -f pcretest pcregrep )
( cd ‘/usr/local/bin’ && rm -f pcre-config )
( cd ‘/usr/local/share/doc/pcre’ && rm -f pcre.txt pcre-config.txt pcregrep.txt pcretest.txt AUTHORS COPYING ChangeLog LICENCE NEWS README )
( cd ‘/usr/local/share/doc/pcre/html’ && rm -f NON-AUTOTOOLS-BUILD.txt README.txt index.html pcre-config.html pcre.html pcre16.html pcre32.html pcre_assign_jit_stack.html pcre_compile.html pcre_compile2.html pcre_config.html pcre_copy_named_substring.html pcre_copy_substring.html pcre_dfa_exec.html pcre_exec.html pcre_free_study.html pcre_free_substring.html pcre_free_substring_list.html pcre_fullinfo.html pcre_get_named_substring.html pcre_get_stringnumber.html pcre_get_stringtable_entries.html pcre_get_substring.html pcre_get_substring_list.html pcre_jit_exec.html pcre_jit_stack_alloc.html pcre_jit_stack_free.html pcre_maketables.html pcre_pattern_to_host_byte_order.html pcre_refcount.html pcre_study.html pcre_utf16_to_host_byte_order.html pcre_utf32_to_host_byte_order.html pcre_version.html pcreapi.html pcrebuild.html pcrecallout.html pcrecompat.html pcredemo.html pcregrep.html pcrejit.html pcrelimits.html pcrematching.html pcrepartial.html pcrepattern.html pcreperform.html pcreposix.html pcreprecompile.html pcresample.html pcrestack.html pcresyntax.html pcretest.html pcreunicode.html )
( cd ‘/usr/local/share/doc/pcre/html’ && rm -f pcrecpp.html )
( cd ‘/usr/local/include’ && rm -f pcreposix.h pcrecpp.h pcre_scanner.h )
/bin/bash ./libtool –mode=uninstall rm -f ‘/usr/local/lib/libpcre.la’
libtool: uninstall: rm -f /usr/local/lib/libpcre.la /usr/local/lib/libpcre.so.1.2.7 /usr/local/lib/libpcre.so.1 /usr/local/lib/libpcre.so /usr/local/lib/libpcre.a
/bin/bash ./libtool –mode=uninstall rm -f ‘/usr/local/lib/libpcreposix.la’
libtool: uninstall: rm -f /usr/local/lib/libpcreposix.la /usr/local/lib/libpcreposix.so.0.0.4 /usr/local/lib/libpcreposix.so.0 /usr/local/lib/libpcreposix.so /usr/local/lib/libpcreposix.a
/bin/bash ./libtool –mode=uninstall rm -f ‘/usr/local/lib/libpcrecpp.la’
libtool: uninstall: rm -f /usr/local/lib/libpcrecpp.la /usr/local/lib/libpcrecpp.so.0.0.1 /usr/local/lib/libpcrecpp.so.0 /usr/local/lib/libpcrecpp.so /usr/local/lib/libpcrecpp.a
( cd ‘/usr/local/share/man/man1’ && rm -f pcre-config.1 pcregrep.1 pcretest.1 )
( cd ‘/usr/local/share/man/man3’ && rm -f pcre.3 pcre16.3 pcre32.3 pcre_assign_jit_stack.3 pcre_compile.3 pcre_compile2.3 pcre_config.3 pcre_copy_named_substring.3 pcre_copy_substring.3 pcre_dfa_exec.3 pcre_exec.3 pcre_free_study.3 pcre_free_substring.3 pcre_free_substring_list.3 pcre_fullinfo.3 pcre_get_named_substring.3 pcre_get_stringnumber.3 pcre_get_stringtable_entries.3 pcre_get_substring.3 pcre_get_substring_list.3 pcre_jit_exec.3 pcre_jit_stack_alloc.3 pcre_jit_stack_free.3 pcre_maketables.3 pcre_pattern_to_host_byte_order.3 pcre_refcount.3 pcre_study.3 pcre_utf16_to_host_byte_order.3 pcre_utf32_to_host_byte_order.3 pcre_version.3 pcreapi.3 pcrebuild.3 pcrecallout.3 pcrecompat.3 pcredemo.3 pcrejit.3 pcrelimits.3 pcrematching.3 pcrepartial.3 pcrepattern.3 pcreperform.3 pcreposix.3 pcreprecompile.3 pcresample.3 pcrestack.3 pcresyntax.3 pcreunicode.3 pcrecpp.3 )
( cd ‘/usr/local/include’ && rm -f pcre.h pcrecpparg.h pcre_stringpiece.h )
( cd ‘/usr/local/lib/pkgconfig’ && rm -f libpcre.pc libpcreposix.pc libpcrecpp.pc )
xueliang@dev:~/download/pcre-8.39\$

Linux下安装C compiler (cc)

发表于 2016-06-16 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

系统基于ubuntu server 14.04.4 amd64,即Ubuntu系统的服务器版本,基本适用于桌面版

第一步 检测系统中是否已经安装了C compiler

执行以下命令:

1
cc -v

结果如下:

xueliang@dev:~\$ cc -v
-bash: /usr/bin/cc: No such file or directory
xueliang@dev:~\$

说明没有安装C compiler。

第二步 安装

使用 APT 工具安装 C compiler,很简单,执行如下命令:

1
sudo apt-get install gcc

第三步 验证

验证是否安装成功,执行一下 第一步 的命令即可,结果如下:

Using built-in specs.
COLLECT_GCC=cc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v –with-pkgversion=’Ubuntu 4.8.4-2ubuntu1~14.04.3’ –with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs –enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ –prefix=/usr –program-suffix=-4.8 –enable-shared –enable-linker-build-id –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –with-gxx-include-dir=/usr/include/c++/4.8 –libdir=/usr/lib –enable-nls –with-sysroot=/ –enable-clocale=gnu –enable-libstdcxx-debug –enable-libstdcxx-time=yes –enable-gnu-unique-object –disable-libmudflap –enable-plugin –with-system-zlib –disable-browser-plugin –enable-java-awt=gtk –enable-gtk-cairo –with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre –enable-java-home –with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 –with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 –with-arch-directory=amd64 –with-ecj-jar=/usr/share/java/eclipse-ecj.jar –enable-objc-gc –enable-multiarch –disable-werror –with-arch-32=i686 –with-abi=m64 –with-multilib-list=m32,m64,mx32 –with-tune=generic –enable-checking=release –build=x86_64-linux-gnu –host=x86_64-linux-gnu –target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

说明C compiler安装成功了。


2016年09月10日更新:CentOS 7 安装C compiler

CentOS 7使用 yum 安装C compiler:

1
sudo yum install gcc

js对象转url参数字符串

发表于 2016-04-15 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

参考自 复杂js对象转url参数字符串 - 开源中国社区 并做了优化

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var parseJson2Url = function (param, key) {
var paramStr = '';
var mappingOperator = '=';
var separator = '&';
if (param instanceof String || typeof (param) == 'string' || param instanceof Number || typeof (param) == 'number' || param instanceof Boolean || typeof (param) == 'boolean') {
paramStr += separator + key + mappingOperator + encodeURIComponent(param);
} else {
for (var i in param) {
var value = param[i];
var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
paramStr += separator + parseJson2Url(value, k);
}
}
return paramStr.substr(1);
};

测试

1
2
3
4
5
var json = {'a': 'aaa', 'b': ['b1', 'b2', 'b3'], 'c': [1, new Number(2), new Boolean(3)], 'd': '中文', 'e': {'da': 'dddaaa'}}
var result1 = parseJson2Url(json, 'xyz');
var result2 = parseJson2Url(json);
console.info('result1: ' + result1);
console.info('result2: ' + result2);

测试结果

1
2
result1: xyz.a=aaa&xyz.b[0]=b1&xyz.b[1]=b2&xyz.b[2]=b3&xyz.c[0]=1&xyz.c[1]=2&xyz.c[2]=true&xyz.d=%E4%B8%AD%E6%96%87&xyz.e.da=dddaaa
result2: a=aaa&b[0]=b1&b[1]=b2&b[2]=b3&c[0]=1&c[1]=2&c[2]=true&d=%E4%B8%AD%E6%96%87&e.da=dddaaa

Shell实现Java中String类的常用方法

发表于 2016-04-01 | 更新于 2018-12-01 | | 阅读次数: | 阅读人数:

检测字符串str,从toffset处开始,是否以substr为前缀

注意:$3(即toffset)可以忽略,此时检测字符串$1(即str)是否以$2(substr)为前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# startsWith
function startsWith() {
if [ $# -ne 2 -a $# -ne 3 ]; then
echo "invalid param!"
return
fi
local str="$1"
local substr="$2"
local strLength=${#str}
local substrLength=${#substr}
local toffset=0
if [ $# -eq 3 ]; then
toffset=$3
fi
if [ $toffset -lt 0 -o $toffset -gt $(expr $strLength - $substrLength) ]; then
echo "false"
return
fi
local innerstr="${str:$toffset:$substrLength}"
if [[ "$innerstr" == "$substr" ]]; then
echo "true"
else
echo "false"
fi
}

检测字符串str,是否以substr为后缀

1
2
3
4
5
6
7
8
9
10
11
12
# endsWith
function endsWith() {
if [ $# -ne 2 ]; then
echo "invalid param!"
return
fi
local str="$1"
local substr="$2"
local strLength=${#str}
local substrLength=${#substr}
echo "$(startsWith "$str" "$substr" $(expr $strLength - $substrLength))"
}

根据字符下标,截取字符串

可接收2或3个参数,第1个参数($1)为源字符串(str),第2个参数($2)为截取的开始索引(beginIndex),第3个参数($3)为截取的结束索引(endIndex),若忽略第3个参数,则endIndex为源字符串(str)的长度
注意: 截取的子字符串,包含 beginIndex 位置上的字符,不包含 endIndex 位置上的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# substring
function substring() {
if [ $# -ne 2 -a $# -ne 3 ] ; then
echo "invalid param!"
return
fi
local str="$1"
local strLength=${#str}
local beginIndex=$2
local endIndex=$strLength
if [ $# -eq 3 ]; then
endIndex=$3
fi
if [ $beginIndex -lt 0 ]; then
echo "String index out of range: $beginIndex"
return
fi
if [ $endIndex -gt $strLength ]; then
echo "String index out of range: $endIndex"
return
fi
local substrLength=$(expr $endIndex - $beginIndex)
if [ $substrLength -lt 0 ]; then
echo "String index out of range: $substrLength"
return
fi
echo "${str:$beginIndex:$substrLength}"
}

1234

薛亮

37 日志
45 标签
© 2015 – 2018 薛亮
由 Hexo 强力驱动 v3.8.0
|
主题 – NexT.Muse v6.5.0