Skip to main content

· 10 min read
  • MySQL 之 Explain 输出分析 https://mp.weixin.qq.com/s/yOZ3WglZMZJaV9H7ruzA6g id 查询语句的标识 select_type 查询的类型 table 当前行所查的表 partitions 匹配的分区 type 访问类型 possible_keys 查询可能用到的索引 key mysql 决定采用的索引来优化查询 key_len 索引 key 的长度 ref 显示了之前的表在key列记录的索引中查找值所用的列或常量 rows 查询扫描的行数,预估值,不一定准确 filtered 查询的表行占表的百分比 extra 额外的查询辅助信息

About

MySQL有四种类型的日志:Error LogGeneral Query LogBinary LogSlow Query Log。 第一种错误日志,记录MySQL运行过程ERROR,WARNING,NOTE等信息,系统出错或者某条记录出问题可以查看ERROR日志。 第二种日常运行日志,记录MySQL运行中的每条请求数据。 第三种二进制日志,包含了一些事件,这些事件描述了数据库的改动,如建表、数据改动等,也包括一些潜在改动,主要用于备份恢复、回滚等操作。 第四种慢查询日志,用于MySQL性能调优。

Error Log

MySQL错误日志默认以hostname.err存放在MySQL日志目录,如果不知道MySQL当前的错误日志目录可以使用查询语句:

mysql> show variables like 'log_error';
+---------------+--------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------+
| log_error | /usr/local/var/mysql/mysql-error.log |
+---------------+--------------------------------------+

修改错误日志地址可以在/etc/my.cnf中添加--log-error[=file_name]选项来开启mysql错误日志。

错误日志记录了MySQL Server每次启动和关闭的详细信息以及运行过程中所有较为严重的警告和错误信息。

知道了MySQL错误日志地址,我们就可以查看MySQL错误日志:

2015-09-12 16:03:20 2624 [ERROR] InnoDB: Unable to lock ./ibdata1, error: 35
2015-09-12 16:03:20 2624 [Note] InnoDB: Check that you do not already have another mysqld process using the same InnoDB data or log files.
2015-09-13 00:03:21 2183 [Note] InnoDB: Shutdown completed; log sequence number 426783897

InnoDB: Unable to lock ./ibdata1, error: 35 可以得出资源被抢占,有可能是开了多个MySQL线程。

General Query Log

日常请求的SQL: 添加方式一样在 /etc/my.cnf 中添加 general-log-file[=file_name]

查看状态

show global variables like "%genera%";

因为为了性能考虑,一般general log不会开启。 slow log可以定位一些有性能问题的sql,而general log会记录所有的SQL。 mysql5.0版本,如果要开启slow log、general log,需要重启, 从MySQL5.1.6版开始,general query log和slow query log开始支持写到文件或者数据库表两种方式, 并且日志的开启,输出方式的修改,都可以在Global级别动态修改。

root@(none) 09:40:33>
select version();
+————+
| version() |
+————+
| 5.1.37-log |
+————+
1 row in set
(0.02 sec)

输出方式

设置日志输出方式为文件(如果设置log_output=table的话,则日志结果会记录到名为gengera_log的表中,这表的默认引擎都是CSV):

root@(none) 09:41:11>
set global log_output = file;
Query OK, 0 rows affected (0.00 sec)

设置日志文件路径

root@(none) 09:45:06>
set global general_log_file =/ tmp / general.log’;
Query OK, 0 rows affected (0.00 sec)

开启general log:

root@(none) 09:45:22>
set global general_log = on;
Query OK, 0 rows affected (0.02 sec)

过一段时间后,关闭general log

root@(none) 09:45:31>
set global general_log = off;
Query OK, 0 rows affected (0.02 sec)

查看tmp/general.log的信息,可以大致看到哪些sql查询/更新/删除/插入比较频繁了。比如有些表不是经常变化的,查询量又很大,就完全可以cache;对主备延迟要求不高的表,读可以放到备库;等等

Binary Log

启用Binlog

修改 /etc/my.cnf

binlog_format = STATEMENT
binlog_cache_size = 2M
max_binlog_cache_size = 4M
max_binlog_size = 512M
log-bin = master-bin
log-bin-index = master-bin.index

log-bin-index 指向 master-bin 这个文件,记录有哪些分块的Binlog文件名。 log-bin 记录Binlog文件名前缀,后缀会用数字递增。

Binlog格式

Binlog有3种格式,STATMENT,ROW,MIXEDhttps://dev.mysql.com/doc/refman/5.1/en/binary-log-mixed.html

混合格式(mixed)会在适当时候切换row和statment格式,statment就是直接的SQL语句格式。

分析Binlog

通过MySQL自带的mysqlbinlog 命令,可以直接查看到Binlog转码数据: mysqlbinlog /usr/local/var/mysql/master-bin.000117 得到:

at 335
150913 0:05:12 server id 1 end_log_pos 366 CRC32 0xa31b50db Xid = 151
COMMIT/*!*/;
DELIMITER ;
End of log file

ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

第一行包含日志文件偏移字节值(335)。

第二行包含:

事件的日期事件,MySQL会使用他们来产生SET TIMESTAMP 服务器的服务器id end_log_pos 下一个事件的偏移字节 事件类型,这里是Xid,常见的还有其他,例如:Intvar,Query,Stop,Format_desc 原服务器上执行语句的线程id,用于审计和CONNECTION_ID() exec_time对于master端的Binlog来说是执行这个event所花费的时间 原服务器产生的错误代码 通过

mysql> show binlog events;
//也可以的到binlog数据:

| master-bin.000002 | 3861 | Query | 1 | 3954 | BEGIN|
| master-bin.000002 | 3954 | Intvar | 1 | 3986 | INSERT_ID=5|
| master-bin.000002 | 3986 | Query | 1 | 4475 | use `dropbox`; INSERT INTO `UserLog` (`uid`, `fids`, `nids`, `msg`, `log`, `from`, `type`, `ctime`) VALUES ('1', '[\"35\",\"33\",\"21\"]', '[\"22\",\"21\",\"11\",\"4\",\"3\"]', '从垃圾箱恢复: 恢复文件 \'[\"35\",\"33\",\"21\"]\' 恢复文件夹 \'[\"22\",\"21\",\"11\",\"4\",\"3\"]\'', '[[\"35\",\"33\",\"21\"],[\"22\",\"21\",\"11\",\"4\",\"3\"]]', 'cloud.jue.so', 'recover_by_trash', '2015-09-07 00:51:31')|
| master-bin.000002 | 4475 | Xid | 1 | 4506 | COMMIT /* xid=423 */

查看Binlog信息

mysql> show variables like '%binlog%';
+-----------------------------------------+----------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------+
| binlog_cache_size | 2097152 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_error_action | IGNORE_ERROR |
| binlog_format | STATEMENT |
| binlog_gtid_simple_recovery | OFF |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_rows_query_log_events | OFF |
| binlog_stmt_cache_size | 32768 |
| binlogging_impossible_mode | IGNORE_ERROR |
| innodb_api_enable_binlog | OFF |
| innodb_locks_unsafe_for_binlog | OFF |
| max_binlog_cache_size | 4194304 |
| max_binlog_size | 536870912 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| simplified_binlog_gtid_recovery | OFF |
+-----------------------------------------+----------------------+

Slow Query Log

开启 Slow Query

修改/etc/my.cnf

slow-query-log = 1
slow-query-log-file = /usr/loval/var/mysql/mysql-slow.log
long_query_time = 1 #设置满请求时间
log-queries-not-using-indexes

Slow Query工具

Slow Query有很多查看工具,比如:MySQL自带的mysqldumpslow 和 mysqlsla,用的比较多的 py-query-digest,还可以将满请求数据丢给zabbix做显示分析处理。

这里我用 py-query-digest /usr/local/var/mysql/mysql-slow.log 导出了满请求的数据,例如:

# Query 1: 0.02 QPS, 0.55x concurrency, ID 0xFC19E4D04D8E60BF at byte 12547
# This item is included in the report because it matches --limit.
# Scores: V/M = 118.26
# Time range: 2015-09-12 05:52:03 to 05:57:54
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 1 7
# Exec time 78 194s 250ms 169s 28s 167s 57s 992ms
# Lock time 0 901us 111us 158us 128us 152us 18us 119us
# Rows sent 0 5 0 1 0.71 0.99 0.45 0.99
# Rows examine 7 545.01k 14.18k 97.66k 77.86k 97.04k 32.08k 97.04k
# Query size 0 868 123 125 124 124.25 1 118.34
# String:
# Databases mysqltest
# Hosts localhost
# Users root
# Query_time distribution
# 1us
# 10us
# 100us
# 1ms
# 10ms
# 100ms ################################################################
# 1s ##########################################
# 10s+ ##########################################
# Tables
# SHOW TABLE STATUS FROM `mysqltest` LIKE 'File'\G
# SHOW CREATE TABLE `mysqltest`.`File`\G
# SHOW TABLE STATUS FROM `mysqltest` LIKE 'User'\G
# SHOW CREATE TABLE `mysqltest`.`User`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT count(*)
FROM `File`
LEFT JOIN `User` ON `User`.`name` = `File`.`name`
WHERE `User`.`name` LIKE '%r%'
order by `last`\G

可以看到该SQL被调用7次,平均每次28s,好慢...平均检测数据大小77.86k。

再来看看SQL语句:

SELECT count(*)
FROM File
LEFT JOIN User ON User.name = File.name
WHERE User.name LIKE '%r%'
order by last

看着都觉得慢 ON User.name= File.name 在没有建立索引的情况下,所有数据将进行字符串匹配name字段。

这个库有 15W条User数据,10W条File数据,也就是要比对15*10 WW 次数据。

MySQL的slow log的作用也就在这里了,优化慢查询。

参考:

1.《高性能MySQL》

2.(Analyse slow-query-log using mysqldumpslow & pt-query-digest)[https://rtcamp.com/tutorials/mysql/slow-query-log/]

3.初探:MySQL 的 Binlog&version=11020201&pass_ticket=DNtPK7ePVYl93tx1FiRMBNsJMm3DEgwRdO1XEZUustRXuYf6KyUU4gID1Lv7aVTB)

· 7 min read
mysql> show processlist;
+—–+————-+——————–+
| Id | User | Host | db | Command | Time| State | Info
+—–+————-+——————–+
|207|root |192.168.0.2:51621 |mytest | Sleep | 5 | | NULL
|208|root |192.168.0.2:51622 |mytest | Sleep | 5 | | NULL
|220|root |192.168.0.2:51676 |mytest |Query | 84 | locked |
select name,culture,value,type from book where id=1
说明各列的含义和用途,
id列:一个标识,你要kill 一个语句的时候很有用。
user列: 显示当前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。
host列:显示这个语句是从哪个ip 的哪个端口上发出的。可用来追踪出问题语句的用户。
db列:显示这个进程目前连接的是哪个数据库。
command列:显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
time列:此这个状态持续的时间,单位是秒。
state列:显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个sql语句,已查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成。
info列:显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于 tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行 FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理 SELECT 查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为 GROUP BY 做排序。
Sorting for order
正在为 ORDER BY 做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执 ALTER TABLE 或 LOCK TABLE 语句行完以前,数据表无法被其他线程打开。 正尝试打开一个表。
Removing duplicates
正在执行一个 SELECT DISTINCT 方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比 Repair by sorting 慢些。
Searching rows for update
正在讲符合条件的记录找出来以备更新。它必须在 UPDATE 要修改相关的记录之前就完成了。
Sleeping
正在等待客户端发送新请求.
System lock
正在等待取得一个外部的系统锁。如果当前没有运行多个 mysqld 服务器同时请求同一个表,那么可以通过增加 –skip-external-locking参数来禁止外部系统锁。
Upgrading lock
INSERT DELAYED 正在尝试取得一个锁表以插入新记录。
Updating
正在搜索匹配的记录,并且修改它们。
User Lock
正在等待 GET_LOCK()。
Waiting for tables
该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, 或 OPTIMIZE TABLE。
waiting for handler insert
INSERT DELAYED 已经处理完了所有待处理的插入操作,正在等待新的请求。
大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。还有其它的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。

· One min read

auth

update user
set host = '10.%.%.%'
where user = 'root';
select host, user
from user;

-- 只读账号
GRANT SELECT ON *.* TO 'read'@'%' IDENTIFIED BY '12341234';

-- 8.0 bug fix mysql_native_password
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '12341234';

user表每天注册数

SELECT from_unixtime(regdate, '%Y-%m-%d') AS regymd,
count(1) AS num
FROM v9_member
GROUP BY regymd
ORDER BY regymd ASC;

日数据 以每月排

SELECT from_unixtime(time, '%Y%m') AS M,
count(1) AS day_num,
sum(payment_total) AS payment_m
FROM echo_register_payment_info
GROUP BY M
ORDER BY m DESC;

复制表

CREATE TABLE `echo_total_databank`.`echo_controller2cname`
(
`id` INT(11) NOT NULL,
`ename` VARCHAR(100) DEFAULT NULL,
`cname` VARCHAR(100) DEFAULT NULL,
`type` VARCHAR(10) DEFAULT NULL
) ENGINE = MyISAM
DEFAULT CHARSET = utf8 COMMENT = 'echo-last-page-info控制器名称对应';

ALTER TABLE `echo_total_databank`.`echo_controller2cname`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `un` (`ename`) USING BTREE;

ALTER TABLE `echo_total_databank`.`echo_controller2cname`
MODIFY `id` INT(11) NOT NULL AUTO_INCREMENT;

SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';

INSERT INTO `echo_total_databank`.`echo_controller2cname`
SELECT *
FROM `databank`.`echo_controller2cname`;

· One min read

docker exec mysql-1 sh -c 'mysqldump --all-databases -uroot -p12341234' > /www/1.sql docker exec mysql-1 sh -c 'mysqldump -uroot -p12341234' gfTest > /www/1.sql

导出 sh

Now=$(date +"%Y%m%d_%H%M%S");
File=gaojian_$Now.sql;

/alidata/server/mysql-5.6.21/bin/mysqldump -h127.0.0.1 -ugaojian -p'gaojian123' gaojian > /alidata/www/gaojian/caches/bakup/sql/$File;

mysqldump -hlocalhost -uhaohe_test -p'iy9nPKJV' --skip-lock-tables pcmoto > ./a.sql

echo "Your Database Backup Successfully Completed";

导入

source d:\1.sql

docker exec mysql-1 sh -c 'mysqldump --all-databases -uroot -pbitdata' > /www/11_23.sql docker exec mysql-1 sh -c 'mysqldump --databases coin -uroot -pbitdata' > /www/2.sql

mysqldump -u root -p --compatible=postgresql --default-character-set=utf8 at-dev > 1.sql

docker exec mysql-1 sh -c 'mysql -uroot -pbitdata' < /www/11_23.sql

create database coin default character set utf8mb4;

docker run --restart=unless-stopped --name mysql-2 -it -d -v "$PWD":/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=bitdata mysql:5.6.39 --character-set-server=utf8 --collation-server=utf8_general_ci

source 加速

SET GLOBAL foreign_key_checks=0; SET GLOBAL unique_checks=0; SET GLOBAL innodb_flush_log_at_trx_commit=0; SET GLOBAL sync_binlog=0;

SET GLOBAL foreign_key_checks=1; SET GLOBAL unique_checks=1; SET GLOBAL innodb_flush_log_at_trx_commit=1; SET GLOBAL sync_binlog=1;

· One min read

· 7 min read

pic

sort.png

名词解释

n: 数据规模
k:“桶”的个数
In-place: 占用常数内存,不占用额外内存
Out-place: 占用额外内存
稳定性:排序后2个相等键值的顺序和排序之前它们的顺序相同

10

var a = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48]

冒泡排序(Bubble Sort)

function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) { //相邻元素两两对比
var temp = arr[j + 1]; //元素交换
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}

选择排序(Selection Sort)

function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { //寻找最小的数
minIndex = j; //将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}

插入排序(Insertion Sort)

function insertionSort(arr) {
var len = arr.length;
var preIndex, current;
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = current;
}
return arr;
}

希尔排序(Shell Sort)

function shellSort(arr) {
var len = arr.length,
temp,
gap = 1;
while (gap < len / 3) { //动态定义间隔序列
gap = gap * 3 + 1;
}
for (gap; gap > 0; gap = Math.floor(gap / 3)) {
for (var i = gap; i < len; i++) {
temp = arr[i];
for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = temp;
}
}
return arr;
}

归并排序(Merge Sort)

function mergeSort(arr) { //采用自上而下的递归方法
var len = arr.length;
if (len < 2) {
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
var result = [];

while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}

while (left.length)
result.push(left.shift());

while (right.length)
result.push(right.shift());

return result;
}

快速排序(Quick Sort)

function quickSort(arr, left, right) {
var len = arr.length,
partitionIndex,
left = typeof left != 'number' ? 0 : left,
right = typeof right != 'number' ? len - 1 : right;

if (left < right) {
partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}

function partition(arr, left, right) { //分区操作
var pivot = left, //设定基准值(pivot)
index = pivot + 1;
for (var i = index; i <= right; i++) {
if (arr[i] < arr[pivot]) {
swap(arr, i, index);
index++;
}
}
swap(arr, pivot, index - 1);
return index - 1;
}

function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

堆排序(Heap Sort)

var len; //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) { //建立大顶堆
len = arr.length;
for (var i = Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i);
}
}

function heapify(arr, i) { //堆调整
var left = 2 * i + 1,
right = 2 * i + 2,
largest = i;

if (left < len && arr[left] > arr[largest]) {
largest = left;
}

if (right < len && arr[right] > arr[largest]) {
largest = right;
}

if (largest != i) {
swap(arr, i, largest);
heapify(arr, largest);
}
}

function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

function heapSort(arr) {
buildMaxHeap(arr);

for (var i = arr.length - 1; i > 0; i--) {
swap(arr, 0, i);
len--;
heapify(arr, 0);
}
return arr;
}

计数排序(Counting Sort)

function countingSort(arr, maxValue) {
var bucket = new Array(maxValue + 1),
sortedIndex = 0;
arrLen = arr.length,
bucketLen = maxValue + 1;

for (var i = 0; i < arrLen; i++) {
if (!bucket[arr[i]]) {
bucket[arr[i]] = 0;
}
bucket[arr[i]]++;
}

for (var j = 0; j < bucketLen; j++) {
while (bucket[j] > 0) {
arr[sortedIndex++] = j;
bucket[j]--;
}
}

return arr;
}

桶排序(Bucket Sort)

function bucketSort(arr, bucketSize) {
if (arr.length === 0) {
return arr;
}

var i;
var minValue = arr[0];
var maxValue = arr[0];
for (i = 1; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i]; //输入数据的最小值
} else if (arr[i] > maxValue) {
maxValue = arr[i]; //输入数据的最大值
}
}

//桶的初始化
var DEFAULT_BUCKET_SIZE = 5; //设置桶的默认数量为5
bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
var buckets = new Array(bucketCount);
for (i = 0; i < buckets.length; i++) {
buckets[i] = [];
}

//利用映射函数将数据分配到各个桶中
for (i = 0; i < arr.length; i++) {
buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
}

arr.length = 0;
for (i = 0; i < buckets.length; i++) {
insertionSort(buckets[i]); //对每个桶进行排序,这里使用了插入排序
for (var j = 0; j < buckets[i].length; j++) {
arr.push(buckets[i][j]);
}
}

return arr;
}

基数排序(Radix Sort)

var counter = [];

function radixSort(arr, maxDigit) {
var mod = 10;
var dev = 1;
for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
for (var j = 0; j < arr.length; j++) {
var bucket = parseInt((arr[j] % mod) / dev);
if (counter[bucket] == null) {
counter[bucket] = [];
}
counter[bucket].push(arr[j]);
}
var pos = 0;
for (var j = 0; j < counter.length; j++) {
var value = null;
if (counter[j] != null) {
while ((value = counter[j].shift()) != null) {
arr[pos++] = value;
}
}
}
}
return arr;
}

· One min read
docker run --restart=unless-stopped --name pmd -d -p 33060:80 phpmyadmin/phpmyadmin:4.7

docker exec -it pmd sh

vi /etc/phpmyadmin/config.user.inc.php

supervisorctl restart all

/etc/phpmyadmin/config.user.inc.php

<?php

// vi /etc/phpmyadmin/config.user.inc.php

$cfg['Servers'] = [];

$cfg['Servers'][1] = [
'auth_type' => 'cookie',
'connect_type' => 'tcp',
'compress' => false,
'AllowNoPassword' => true,
'host' => '139.196.x.x',
'user' => 'root',
];

$cfg['Servers'][] = [
'auth_type' => 'config',
'connect_type' => 'tcp',
'compress' => false,
'AllowNoPassword' => true,
'host' => 'x.x.x.x', // 本机
'user' => 'root',
'password' => 'xxxx',
];

· 3 min read

下载地址

centos http://www.centoscn.com/CentosSoft/
jdk1.7 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
hadoop http://apache.fayea.com/hadoop/common/

修改eth0
cat /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.1.101
NETMASK=255.255.255.0
GATEWAY=192.168.1.1

关闭iptables
service iptables stop
chkconfig iptables off

# selinux 关闭
/etc/selinux/config
SELINUX=disabled

配置dns
/etc/resolv.conf
nameserver 180.168.255.118

rm -f /etc/udev/rules.d/70-persistent-net.rules #mac地址conf

mount -t vboxsf BaiduShare /mnt/bdshare/

jdk 安装


jdk 安装配置
rpm -ivh jdk-7u79-linux-x64.rpm
cd /usr/java/
vi ~/.bashrc
export JAVA_HOME=/usr/java/latest
export PATH=$PATH:$JAVA_HOME/bin
env | grep JAVA
reboot
env | grep JAVA

02.hdfs单机和集群的配置安装

hadoop 下载安装

wget http://apache.fayea.com/hadoop/common/hadoop-2.5.2/hadoop-2.5.2.tar.gz
md5sum hadoop-2.6.0.tar.gz | tr "a-z" "A-Z"
tar -zxvf hadoop-2.5.2.tar.gz
ln -sf hadoop-2.5.2 hadoop #链接

vi ~/.bashrc
export JAVA_HOME=/usr/java/latest
export HADOOP_HOME=/bao/hadoop
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

无密码登录

ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

配置看官方文档

Single Node Setup

C:\Windows\System32\drivers\etc\hosts
vi /etc/hosts
192.168.1.201 hadoop1

vi core-site.xml # /bao/hadoop/etc/hadoop
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://hadoop1:9000</value>
</property>
</configuration>

vi hdfs-site.xml # /bao/hadoop/etc/hadoop
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/hdata/namenode</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/hdata/datanode</value>
</property>
<property>
<name>dfs.tmp.dir</name>
<value>/hdata/tmp</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value><!-- 大约0 0:Requested replication 0 is less than the required minimum 1 -->
</property>
</configuration>

vi slaves # /bao/hadoop/etc/hadoop
hadoop1

初始化 启动

hdfs namenode -format

start-dfs.sh
stop-dfs.sh

jps #看进程
netstat -anp | grep java

log

cd /bao/hadoop/logs
tail -n50 -f hadoop-root-namenode-localhost.localdomain.log

curd

hdfs dfs -put /bao/hadoop-2.5.2.tar.gz /
hdfs dfs -ls /

集群

复制一个hadoop2

hostnamectl set-hostname hadoop2

vi hdfs-site.xml # /bao/hadoop/etc/hadoop
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/hdata/namenode</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/hdata/datanode</value>
</property>
<property>
<name>dfs.tmp.dir</name>
<value>/hdata/tmp</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value><!-- 大约0 0:Requested replication 0 is less than the required minimum 1 -->
</property>
</configuration>

vi slaves # /bao/hadoop/etc/hadoop
hadoop1
hadoop2

初始化启动

cd /hdata
rm -rf *

stop-dfs.sh
hdfs namenode -format
start-dfs.sh

# http://192.168.1.201:50070/dfshealth.html#tab-datanode
检查是不是有两个 Node
#hadoop checknative -a #检查
#warn

yum -y install svn ncurses-devel gcc*
yum -y install lzo-devel zlib-devel autoconf automake libtool cmake openssl –devel

#安装 protobuf(不安装,编译将无法完成)
Hadoop使用protocol buffer进行通信,需要下载和安装protobhf-2.5.0.tar.gz
cd protobuf - 2.5.0
./configure
make
make install
protoc –-version

cd /hadoop-2.5.2-src
mvn package -Pdist,native -DskipTests -Dtar

export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR="/app/hadoop/lib/native"
export HADOOP_OPTS="-Djava.library.path=/app/hadoop/lib/native"

03.hdfs应用-云存储系统1

windows java

eclipse-jee-luna-R-win32-x86_64.zip
jdk-7u45-nb-7_4-windows-x64.exe

A:\eclipse\eclipse.ini
-vm
C:\Program Files\Java\jdk1.7.0_45\bin

jetty

Help -> Eclipse Marketplace
Search jetty
Run-Jetty-Run install

maven

File -> New -> Maven Project
maven-archetype-webapp

web -> Bulid Path -> Configure Bulid Path
Jave Bulid Path -> Soure -> 2个missing 的 Remove

web -> Source Foloer
src/main/java
src/main/test

web -> Bulid Path -> Configure Bulid Path
Jave Bulid Path -> Output folder -> target/classes * 3

Peferences -> jre -> Installed JREs -> Check version

web -> Bulid Path -> Configure Bulid Path
Libraries -> JRE -> Edit -> Workspace default JRE

06.hdfs应用-云存储系统4

· 2 min read

gpio-pin.png

gpio.py
# pip install rpi.gpio
import time

import RPi.GPIO as GPIO

# https://blog.csdn.net/guzhong10/article/details/80119322

# gpio mode 0 out
# gpio write 0 1



GPIO.setwarnings(False)

GPIO_PIN = 26

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN, GPIO.OUT)

# L_Motor = GPIO.PWM(GPIO_PIN, 100)
# L_Motor.start(0)

while True:
GPIO.output(GPIO_PIN, GPIO.HIGH)
time.sleep(.5)
print(GPIO.input(GPIO_PIN))

# while True:
# GPIO.output(i, 1)
# time.sleep(1)
# GPIO.output(i, 0)
# time.sleep(1)
run.py
import time

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM) # 设置引脚的编码方式

delay = 5 # delay 2ms

pin_1 = 6
pin_2 = 13
pin_3 = 19
pin_4 = 26


def init():
GPIO.setwarnings(False)
GPIO.setup(pin_1, GPIO.OUT)
GPIO.setup(pin_2, GPIO.OUT)
GPIO.setup(pin_3, GPIO.OUT)
GPIO.setup(pin_4, GPIO.OUT)


def forward(delay):
setStep(1, 0, 0, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 0, 0, 1)
time.sleep(delay)


def setStep(w1, w2, w3, w4):
# print(w1, w2, w3, w4)
GPIO.output(pin_1, w1)
GPIO.output(pin_2, w2)
GPIO.output(pin_3, w3)
GPIO.output(pin_4, w4)


init()
while True:
forward(delay / 1000.0)
test.py
import time

import RPi.GPIO as GPIO

delay = 5 # delay 2ms

pin_1 = 6
pin_2 = 13
pin_3 = 19
pin_4 = 26
pin_1 = 26
pin_2 = 19
pin_3 = 13
pin_4 = 6

GPIO.setmode(GPIO.BCM) # 设置引脚的编码方式


def init():
GPIO.setwarnings(False)
GPIO.setup(pin_1, GPIO.OUT)
GPIO.setup(pin_2, GPIO.OUT)
GPIO.setup(pin_3, GPIO.OUT)
GPIO.setup(pin_4, GPIO.OUT)


def forward(delay):
setStep(1, 0, 0, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 0, 0, 1)
time.sleep(delay)


def setStep(w1, w2, w3, w4):
# print(w1, w2, w3, w4)
GPIO.output(pin_1, w1)
GPIO.output(pin_2, w2)
GPIO.output(pin_3, w3)
GPIO.output(pin_4, w4)


def main():
init()
while True:
forward(delay / 1000.0)


main() # 调用main