MySQL 批量插入、批量更新

MySQL 批量插入/更新含有主键/唯一索引或者的解决方案是使用 on duplicate key update

解决方案

insert into database.table (id, key, field)
    values (v1, v2, v3), (v1, v2, v3), (v1, v2, v3)
    on duplicate key update
    id=values(id),key=values(key),field=values(field);

该方案适用范围广,
既可以批量插入,
也可以批量更新,
同时能保证避免插入重复数据,
还能避免影响自增 id,
又不需要创建临时表权限,
更不会修改已存在记录的其他字段。


实际应用中 update 后跟随的字段可以进行调整,保留只需要更新的字段


如果表中有自增 id,这个方案还有一点需要注意,insert into … values 跟随的记录数 (numberA)即为此次自增数 (numberA),即使存在重复唯一索引导致实际插入记录数(numberB)少于跟随的记录数(numberA)。


其他插入方案

1. insert ignore into

insert ignore 遇到重复数据会忽略,可以有效保证不插入重复数据,但也会忽略其他错误。
批量插入之后再进行单条更新。

# 批量插入,需要保证 NOT NULL 字段有值
insert into database.table (id, key, field)
    values (v1, v2, v3), (v1, v2, v3), (v1, v2, v3);

# 单条更新
update database.table set field = v3 where key = v1;
update database.table set field = v3 where key = v1;
update database.table set field = v3 where key = v1;

2. replace into

如果表中有主键或唯一索引,replace into 会删除冲突行(已存在记录),再新插入新行。因此导致 replace into 可能会导致主键自增 1。
如果表中没有主键和唯一索引,replace into 没有意义。

如果表中没有自增主键,使用 replace into 是一个不错的选择。

使用 replace 需要注意,如果 更新的字段 不全,会被设置为缺省值,也就是会清除其他字段。

replace into database.table (id, key, field)
    values (v1, v2, v3), (v1, v2, v3), (v1, v2, v3);

最后,推荐使用 insert into … on duplicate key update

on duplicate key update 是 mysql 特有语法。

MySQL root 密码丢失重置

前几周百度云同步时把重要文件误删,包括 mysql root 密码。

MySQL root 密码丢失,需要以类似 mysqld_safe –skip-grant-tables 方式运行,才能让 mysql -uroot 顺利执行,登录到 mysql 命令行。

如果 mysql 在运行,先将 mysql 运行方式记录下来

> ps aux | grep mysql
// 假设当前 mysql 运行命令如下,实际参数可能更复杂
/mysql/bin/mysqld --pid-file=/mysql/mysql.pid --socket=/tmp/mysql.sock

1. 关闭 mysql 进程

不要使用 kill 命令直接结束,而是通过 stop 参数结束 mysql 进程。

// 假设 mysql 启动命令是
// /etc/init.d/mysql start
// 则应该通过如下方式结束 mysql 进程
> /etc/init.d/mysql stop

2. 以 –skip-grant-tables 方式启动 mysql

在原有 mysql 运行命令基础上加上 –skip-grant-tables &,& 表示放入当前会话 background。

/mysql/bin/mysqld --pid-file=/mysql/mysql.pid --socket=/tmp/mysql.sock --skip-grant-tables &

3. 登录 mysql 修改 root 密码

> mysql -uroot
> update mysql.user set password=PASSWORD('MysqlRoot') where user='root';

4. 参考第 1 步,结束 mysql 进程

5. 执行原有 mysql 启动命令

// 假设 mysql 启动命令如下
> /etc/init.d/mysql start

使用 root 新密码登录 mysql

> mysql -uroot -p
Enter password: 

密码重置完成。

重置过程有两点需要注意:

  1. 不推荐使用 kill 结束 mysql 进程;
  2. 以 –skip-grant-tables 方式运行 mysql 需要保留原有参数

Linux 常见解压与压缩

Linux 压缩与解压命令

格式 解压 压缩
 
tar
(仅打包不压缩)
tar -xvf [原文件名].tar tar -cvf [目标文件名].tar [原文件名/目录名]
 
tar.bz2 bunzip2 [原文件名].tar.bz2 bzip2 [原文件名].tar
tar.bz2
(通过 tar 调用)
tar -jxvf [原文件名].tar.bz2 tar -jcvf [目标文件名].tar.bz2 [原文件名/目录名]
 
tar.gz gunzip [原文件名].tar.gz gzip [原文件名].tar
tar.gz
(通过 tar 调用)
tar -zxvf [原文件名].tar.gz tar -zcvf [目标文件名].tar.gz [原文件名/目录名]
 
tar.xz unxz [原文件名].tar.xz xz [原文件名].tar
tar.xz
(通过 tar 调用)
tar -Jxvf [原文件名].tar.xz tar -Jcvf [目标文件名].tar.xz [原文件名/目录名]
 
tar.Z
(已过时)
uncompress [原文件名].tar.Z compress [原文件名].tar
tar.Z
(通过 tar 调用)
tar -Zxvf [原文件名].tar.Z tar -Zcvf [目标文件名].tar.Z [原文件名/目录名]
 
7z 7z x [原文件名].7z 7z a [目标文件名].7z [原文件名/目录名]
 
jar jar -xvf [原文件名].jar jar -cvf [目标文件名].jar [原文件名/目录名]
 
zip unzip [原文件名].zip zip -r [目标文件名].zip [原文件名/目录名]

JavaScript 浮点数计算问题

JavaScript 浮点数神坑当属 0.1 + 0.2 == 0.3false

> 0.1 + 0.2 == 0.3
false
> 0.1 + 0.2
0.30000000000000004
>

还有一些比较隐蔽的问题,比如 Math.roundNumber.prototype.toFixed 也都不是能完全正常工作的。

> Math.round(1.105 * 100)
111
> Math.round(1.015 * 100)
101
> Math.round(1.025 * 100)
102
> 0.25.toFixed(1)
'0.3'
> 0.35.toFixed(1)
'0.3'

Math.round、toFixed 计算出错主要因为浮点数不能精确表示。

在这里 0.35 和 1.015 的值都不准确,一个办法是转换成整数计算再除以对应的十百千;另一个办法是采用现有的 lib,比如 accounting

> 1.015 * 100
101.49999999999999

代码运行环境

D:\node -v
v8.1.0

安装 Nginx、Lua,使用 Lua 扩展 Nginx

使用 lua-nginx-module 可以让 Nginx 通过一些指令如 content_by_lua、content_by_lua_file 运行 Lua 脚本,非常方便。

先下载所需文件

1. 安装 luajit,官网 http://luajit.org/install.html

解压之后直接 make

make PREFIX=/usr/local/luajit

2. 下载 ngx_devel_kit(github)、nginx_lua_module(github

3. 进入 nginx 源码目录准备 configure

如果已经安装 nginx,也可以再次 configure,但一定要涵盖上次使用的参数。

4. 导出 LUAJIT_LIB、LUAJIT_INC 环境变量

export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

LUAJIT_LIB 对应 libluajit-5.1.so 文件所在目录
LUAJIT_INC 对应 lua.h 文件所在目录

目录可能不一样,但参考 LUAJIT_LIB、LUAJIT_INC 含义。

5. 在 nginx-1.10.2 目录执行 ./configure

./configure \
--prefix=/usr/local/nginx \
--with-http_flv_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_v2_module \
--with-ipv6 \
--with-ld-opt="-ljemalloc,-Wl,-rpath,/usr/local/luajit/lib" \
--with-openssl=/opt/src/openssl-1.0.2l \
--with-pcre=/opt/src/pcre-8.40 \
--with-pcre-jit \
--add-module=/opt/src/ngx_devel_kit-0.3.0 \
--add-module=/opt/src/lua-nginx-module-0.10.8

这里用到了 ljemalloc、openssl、pcre 可以预先安装

安装 jemalloc,进入 jemalloc-4.2.1

./configure
make
make install

安装 openssl pcre,或者进入源码目录安装

yum install openssl openssl-devel
yum install pcre pcre-devel

6. 测试执行 lua

在 Nginx 某个 server 下增加

location /hello { 
    content_by_lua 'ngx.say("Hello, Lua")'; 
}

尝试访问

[root@CentOS-58 06]# curl lua.zhengxianjun.com/hello
Hello, Lua!

安装成功并且正常运行。

如果对 nginx 安装目录进行版本管理,会发现 make install 完成之后只有 nginx/sbin/nginx 文件有改动。

安装完成之后切记要执行 sbin/ngxin -t 检查语法是否正确。
一定要安装正确才能执行 sbin/ngxin -s reload 。

因为对于已经安装的 nginx,如果 ./configure 没有覆盖上一次的参数,会导致某些功能失效。
第一次 configure 时没有添加 –with-http_ssl_module 导致 nginx 提示 unknown directive “ssl”。