目录

文章目录

  • 目录
  • 1. 引言
  • 2. 工具说明
    • 2.1 使用方式
    • 2.2 选项说明
  • 3. 工作流程
  • 4. 实例
    • 4.1 表归档到表(逐行进行)
    • 4.2 表归档到表(批量进行)
      • 4.2.1 归档到当前实例,并删除数据
      • 4.2.2 归档到远程实例,不删除数据
    • 4.3 仅清除表数据
    • 4.4 表自增字段处理
  • 5. 总结

1. 引言

2. 工具说明

2.1 使用方式

pt-archiver [OPTIONS] --source DSN --where WHERE

2.2 选项说明

选项 说明
–analyze 指定工具执行完成后对表的优化,如’–analyze=ds’,s代表源端表,d代表目标端表,也可以单独指定。
–ask-pass 命令行提示密码输入,保护密码安全,前提需安装模块 perl-TermReadKey
–buffer 指定缓冲区数据刷新到选项’–file’指定的文件并且在提交时刷新。只有当事务提交时禁用自动刷新到’–file’指定的文件和刷新文件到磁盘,这意味着文件是被操作系统块进行刷新,因此在事务进行提交之前有一些数据隐式刷新到磁盘。默认是每一行操作后进行文件刷新到磁盘。性能可以提升5%~15%
–bulk-delete 指定单个语句删除chunk的方式来批量删除行,会隐式执行选项’–commit-each’。使用单个DELETE语句删除每个chunk对应的表行,通常的做法是通过主键进行逐行的删除,批量删除在速度上会有很大的提升,但如果有复杂的’WHERE’条件就可能会更慢。注意:搭配–purge和 --bulk-insert 一起使用生效!!!
–[no]bulk-delete-limit 默认值:yes,指定添加选项’–bulk-delete’和’–limit’到进行归档的语句中
–bulk-insert 使用LOAD DATA LOCAL INFILE的方法,通过批量插入chunk的方式来插入行(隐式指定选项’–bulk-delete’和’–commit-each’)而不是通过逐行单独插入的方式进行,它比单行执行INSERT语句插入的速度要快。通过隐式创建临时表来存储需要批量插入的行(chunk),而不是直接进行批量插入操作,当临时表中完成每个chunk之后再进行统一数据加载。为了保证数据的安全性,该选项会强制使用选项’–bulk-delete’,这样能够有效保证删除是在插入完全成功之后进行的 。–low-priority-insert, --replace, 和 --ignore 与此选项共同使用
–channel channel的名称。指定当主从复制环境是多源复制时需要进行归档哪个主库的数据,适用于多源复制中多个主库对应一个从库的情形
–charset string类型;指定连接字符集,连接MySQL之后通过执行SET NAMES UTF8 命令实现。只能是MySQL识别的字符编码
–[no]check-charset 默认值:yes。指定检查确保数据库连接时字符集和表字符集相同。需要做编码转换是需要使用此选项。
–[no]check-columns 默认值:yes。指定检查确保选项’–source’指定的源端表和’–dest’指定的目标表具有相同的字段。不检查字段在表的排序和字段类型,只检查字段是否在源端表和目标表当中都存在,如果有不相同的字段差异,则工具报错退出。如果需要禁用该检查,则指定’–no-check-columns’
–check-interval 时间类型,默认是1s;若添加了--check-slave-lag选项,则当前选项定义了每一次工具发现从库延迟之后所暂停的时间,每100行执行一次
–check-slave-lag 指定主从复制延迟大于选项’–max-lag’指定值之后暂停归档操作。默认情况下,工具会检查所有的从库,但该选项只作用于指定的从库(通过DSN连接方式)
–columns 指定需要归档的字段,如有多个则用’,’(逗号)分隔
–commit-each 指定按每次获取和归档的行数进行提交,该选项会禁用选项’–txn-size’。在每次获取表数据并进行归档之后,在获取下一次数据和选项’–sleep’指定的休眠时间之前,进行事务提交和刷新选项’–file’指定的文件,通过选项’–limit’控制事务的大小。
–config 指定配置文件,如有多个则用’,’(逗号)分隔,必须是命令行的第一个参数
–host 指定连接的数据库IP地址
–port 指定连接的数据库Port端口
–user 指定连接的数据库用户
–password 指定连接的数据库用户密码
–socket 指定使用的SOCKET套接字
–databases 指定连接的数据库
–source 必须项,指定需要进行归档操作的表,使用DSN方式表示
–dest 指定要归档到的目标端表,使用DSN方式表示。如果该选项没有指定的话,则默认与选项’–source’指定源端表为相同表。
–where 指定通过WHERE条件语句指定需要归档的数据,该选项是必须指定的选项。不需要加上’WHERE’关键字,如果确实不需要WHERE条件进行限制,则指定’–where 1=1’
–for-update 指定为每次归档执行的SELECT语句添加FOR UPDATE子句
–share-lock 指定为每次归档执行的SELECT语句添加LOCK IN SHARE MODE子句
–ignore 指定为INSERT语句添加IGNORE选项
–limit 默认值:1,指定每条语句获取表和归档表的行数
–local 不将OPTIMIZE和ANALYZE语句写入binlog
–max-lag 默认值:1s;指定允许主从复制延迟时长的最大值,单位秒。如果在每次获取行数据之后主从延迟超过指定的值,则归档操作将暂停执行,暂停休眠时间为选项’–check-interval’指定的值。待休眠时间结束之后再次检查主从延迟时长,检查方法是通过从库查询的’Seconds_Behind_Master’值来确定。如果主从复制延迟一直大于该参数指定值或者从库停止复制,则操作将一直等待直到从库重新启动并且延迟小于该参数指定值
–no-delete 不删除已被归档的表数据
–optimize 指定工具完成数据归档后对表执行’OPTIMIZE TABLE’操作。指定方法如’–analyze=ds’,s代表源端表,d代表目标端表,也可以单独指定
–primary-key-only 指定只归档主键字段,是选项’–columns=主键’的简写。如果工具归档的操作是进行DELETE清除时最有效,因为只需读取主键一个字段而无需读取行所有字段
–progress 指定每多少行打印进度信息,打印当前时间,已用时间以及多少行进行归档
–purge 执行清除操作而不是归档操作。允许忽略选项’–dest’和’–file’进行操作,如果只是清除操作可以结合选项’–primary-key-only’会更高效。注意:和–bulk-delete的区别,这才是真正删除源表数据的选项!!!
–quiet 指定工具静默执行,不输出任何的执行信息
–replace 指定写入选项’–dest’指定目标端表时改写INSERT语句为REPLACE语句
–retries 默认值:1;指定归档操作遇死锁或超时的重试次数。当重试次数超过该选项指定的值时,工具将报错退出
–[no]safe-auto-increment 默认值:yes;指定不使用自增列(AUTO_INCREMENT)最大值对应的行进行归档。该选项在进行归档清除时会额外添加一条WHERE子句以防止工具删除单列升序字段具有的AUTO_INCREMENT属性最大值的数据行,为了在数据库重启之后还能使用到AUTO_INCREMENT对应的值,但这会引起无法归档或清除字段对应最大值的行
–set-vars 默认:wait_timeout=10000 innodb_lock_wait_timeout=1 lock_wait_timeout=60;工具归档时指定参数值,如有多个用’,’(逗号)分隔。如’–set-vars=wait_timeout=5000’
–skip-foreign-key-checks 指定使用语句SET FOREIGN_KEY_CHECKS = 0禁用外键检查
–sleep 指定工具在通过SELECT语句获取归档数据需要休眠的时间,默认值是不进行休眠。在休眠之前事务并不会提交,并且选项’–file’指定的文件不会被刷新。如果指定选项’–commit-each’,则在休眠之前会进行事务提交和文件刷新
–statistics 指定工具收集并打印操作的时间统计信息
–txn-size 默认:1;指定每个事务处理的行数。如果是0则禁用事务功能
–version 显示工具的版本并退出
–[no]version-check 默认值:yes;检查Percona Toolkit、MySQL和其他程序的最新版本
–why-quit 指定工具打印当非因完成归档行数退出的原因。在执行一个自动归档任务时该选项与选项’–run-time’一起使用非常方便,这样可以确定归档任务是否在指定的时间内完成。如果同时指定了选项’–statistics’,则会打印所有退出的原因。

DSN选项
DSN是连接数据库的一种方式,DSN选项为key=value方式,在等号的两侧不能有空格出现,并且区分大小写,多个选项之前以’,’(逗号)隔开

选项 说明
a 归档操作是在哪个库下进行的,相当于USE操作
A 指定默认字符集
b 当值为true时,禁止SQL_LOG_BIN,相当于SQL_LOG_BIN = 0
D 指定包含需要归档表的数据库
h 指定连接的主机
u 指定连接的用户
p 指定连接需要的密码
P 指定连接的端口
S 指定连接的SOCKET文件
t 指定需要归档的表
i 指定需要使用的索引

互斥选项:
至少需指定选项–dest、–file或–purge其中之一;

  • –ignore 和 --replace
  • –txn-size 和 --commit-each
  • –low-priority-insert 和 --delayed-insert
  • –share-lock 和 --for-update
  • –analyze 和 --optimize
  • –no-ascend 和 --no-delete

3. 工作流程

4. 实例

** 软件和数据 **

  • 源库和目标库都是:MySQL 8.0.27
  • 模拟数据为用户业务的精简数据结构,如下。

表结构:

CREATE TABLE `user` (`id` int(20) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(11) DEFAULT NULL COMMENT '姓名',`age` int(4) DEFAULT NULL COMMENT '年龄',`address` varchar(256) DEFAULT NULL COMMENT '地址',`create_time` date DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

生成字符串函数:

delimiter $$
CREATE FUNCTION rand_str(n int) RETURNS varchar(255)
begin        declare base_str varchar(100) default "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";declare ret varchar(255) default "";        declare i int default 0;while i < n do        set ret=concat(ret,substring(base_str,floor(1+rand()*62),1));set i= i+1;        end while;        return ret;
end $$
delimiter ;

存储过程循环写数据:

delimiter $$
CREATE  PROCEDURE `insert_data`(IN n int)
BEGIN  DECLARE i INT DEFAULT 1;WHILE (i <= n ) DOINSERT into user (name,age,address,create_time) VALUEs (rand_str(5),FLOOR(RAND() * 100), rand_str(20),now() );set i=i+1;END WHILE;
END $$
delimiter ;

调用存储过程:
CALL insert_data(300000);

测试表的基本信息:

# 最小id、最大id、数据行数
mysql> select min(id),max(id),count(*) from user;
+---------+---------+----------+
| min(id) | max(id) | count(*) |
+---------+---------+----------+
|       1 | 1700000 |  1700000 |
+---------+---------+----------+
1 row in set (0.09 sec)# test库下user表的 自增序号
mysql> select auto_increment from information_schema.tables where table_schema = 'test' and table_name = 'user';
+----------------+
| AUTO_INCREMENT |
+----------------+
|        1700001 |
+----------------+
1 row in set (0.00 sec)

4.1 表归档到表(逐行进行)

说明: 归档表数据,但不删除源端表已归档数据;目标地址和源地址的DSN选项的相同部分是可以省略的,但是为了字面上更加清晰,下文还是会列上。

# 执行命令
pt-archiver \
--source h=127.0.0.1,u=root,p=Abc123654,P=3306,D=test,t=user \
--dest h=127.0.0.1,u=root,p=Abc123654,P=33106,D=destination,t=user \
--charset=utf8 --where 'id<=100' --progress=20 --txn-size=100 --statistics --no-delete# 输出结果
TIME                ELAPSED(耗时)   COUNT(已处理行数)
2022-02-09T17:54:59       0       0
2022-02-09T17:54:59       0      20
2022-02-09T17:54:59       0      40
2022-02-09T17:54:59       0      60
2022-02-09T17:54:59       0      80
2022-02-09T17:54:59       0     100
2022-02-09T17:54:59       0     100
Started at 2022-02-09T17:54:59, ended at 2022-02-09T17:54:59
Source: A=utf8,D=test,P=3306,h=127.0.0.1,p=...,t=user,u=root
Dest:   A=utf8,D=destination,P=33106,h=127.0.0.1,p=...,t=user,u=root
SELECT 100  (源库查询行数)
INSERT 100  (目标库写入行数)
DELETE 0    (源库删除行数)
Action         Count       Time        Pct
select           101     0.0174      39.22
inserting        100     0.0170      38.38
commit             4     0.0047      10.54
other              0     0.0053      11.86

4.2 表归档到表(批量进行)

说明: 批量进行归档涉及的选项是–limit,批量进行插入涉及的选项为–bulk-insert,指定选项–bulk-insert同时也会指定选项–bulk-delete,如果不删除已归档数据,会强制使用–no-delete选项。

4.2.1 归档到当前实例,并删除数据

# 执行命令
pt-archiver \
--source h=127.0.0.1,u=root,p=Lfc123654,P=3306,D=test,t=user \
--dest h=127.0.0.1,u=root,p=Lfc123654,P=3306,D=test,t=dest \
--progress=10 --where 'id<=100' \
--statistics --why-quit --charset=UTF8 --limit=10 --txn-size 10 --purge# 输出
TIME                ELAPSED   COUNT
2022-02-09T18:34:25       0       0
2022-02-09T18:34:25       0      10
2022-02-09T18:34:25       0      20
2022-02-09T18:34:25       0      30
2022-02-09T18:34:25       0      40
2022-02-09T18:34:25       0      50
2022-02-09T18:34:25       0      60
2022-02-09T18:34:25       0      70
2022-02-09T18:34:25       0      80
2022-02-09T18:34:25       0      90
2022-02-09T18:34:25       0     100
2022-02-09T18:34:25       0     100
Started at 2022-02-09T18:34:25, ended at 2022-02-09T18:34:25
Source: A=UTF8,D=test,P=3306,h=127.0.0.1,p=...,t=user,u=root
Dest:   A=UTF8,D=test,P=3306,h=127.0.0.1,p=...,t=dest,u=root
SELECT 100
INSERT 100
DELETE 100
Action         Count       Time        Pct
commit            22     0.0589      56.07
deleting         100     0.0192      18.30
inserting        100     0.0156      14.91
select            11     0.0027       2.58
other              0     0.0085       8.14
Exiting because there are no more rows.# 源表数据
mysql> select * from user where id <=100;
Empty set (0.00 sec)# 目标表数据
mysql> select * from dest where id <=100;
+-----+-------+------+----------------------+-------------+
| id  | name  | age  | address              | create_time |
+-----+-------+------+----------------------+-------------+
|   1 | 06nqQ |   64 | iVA1aBkJtZqWjBRm32S5 | 2022-02-08  |
|   2 | DLJcH |   52 | bIR1lvl1WsiWEjpWlIqO | 2022-02-08  |
|   3 | Ctnib |   72 | IJoBDfaX7zlR5JdHGaDv | 2022-02-08  |
|   4 | uMfII |   11 | 2dPjVwHKwba93HbFE27k | 2022-02-08  |
|   5 | 5i5lj |   22 | OK8hO6TY3cExA7I0MGXx | 2022-02-08  |
......

4.2.2 归档到远程实例,不删除数据

# 执行命令
pt-archiver \
--source h=127.0.0.1,u=root,p=Lfc123654,P=3306,D=test,t=user \
--dest h=127.0.0.1,u=root,p=Abc123654,P=33106,D=destination,t=user \
--charset=utf8 --where 'id<=100' --progress=20 --txn-size=100 --limit=20 --statistics --no-delete# 输出
TIME                ELAPSED   COUNT
2022-02-09T18:02:38       0       0
2022-02-09T18:02:38       0     100
2022-02-09T18:02:38       0     200
2022-02-09T18:02:38       0     300
2022-02-09T18:02:38       0     400
2022-02-09T18:02:38       0     500
2022-02-09T18:02:38       0     600
2022-02-09T18:02:38       0     700
2022-02-09T18:02:38       0     800
2022-02-09T18:02:38       0     900
2022-02-09T18:02:38       0    1000
2022-02-09T18:02:38       0    1000
Started at 2022-02-09T18:02:38, ended at 2022-02-09T18:02:38
Source: A=UTF8,D=test,P=3306,h=127.0.0.1,p=...,t=user,u=root
Dest:   A=UTF8,D=destination,P=33106,h=127.0.0.1,p=...,t=user,u=root
SELECT 1000
INSERT 1000
DELETE 0
Action         Count       Time        Pct(时间占比)
inserting       1000     0.1499      67.25
commit            22     0.0326      14.63
select            11     0.0039       1.75
other              0     0.0365      16.38
Exiting because there are no more rows.

4.3 仅清除表数据

说明:

  1. 先使用选项–dry-run打印查询需要清除数据的执行语句,并确认数据是否准确。
  2. 第一步完成后,指定选项–purge,可以忽略选项–dest或–file,来进行表数据清除操作而不做归档操作。
# 1. 同时指定--purge --dry-run 输出清理的sql,不真正删除数据
pt-archiver \
--source h=127.0.0.1,u=root,p=Abc123654,P=33106,D=destination,t=user \
--progress 20 --where 'id<=200' \
--statistics --charset=UTF8 --limit=20 --txn-size 20 --purge --dry-run# 输出
SELECT /*!40001 SQL_NO_CACHE */ `id`,`name`,`age`,`address`,`create_time` FROM `destination`.`user` FORCE INDEX(`PRIMARY`) WHERE (id<=200) ORDER BY `id` LIMIT 20
SELECT /*!40001 SQL_NO_CACHE */ `id`,`name`,`age`,`address`,`create_time` FROM `destination`.`user` FORCE INDEX(`PRIMARY`) WHERE (id<=200) AND ((`id` >= ?)) ORDER BY `id` LIMIT 20
DELETE FROM `destination`.`user` WHERE (`id` = ?)# 2. 仅指定--purge,真正删除数据,也可以使用选项--bulk-delete进行批量清除
pt-archiver \
--source h=127.0.0.1,u=root,p=Abc123654,P=33106,D=destination,t=user \
--progress 20 --where 'id<=200' \
--statistics --charset=UTF8 --limit=20 --txn-size 20 --purge --bulk-delete# 输出
TIME                ELAPSED   COUNT
2022-02-10T10:12:53       0       0
2022-02-10T10:12:53       0      20
2022-02-10T10:12:53       0      40
2022-02-10T10:12:53       0      60
2022-02-10T10:12:53       0      80
2022-02-10T10:12:53       0     100
2022-02-10T10:12:53       0     120
2022-02-10T10:12:53       0     140
2022-02-10T10:12:53       0     160
2022-02-10T10:12:53       0     180
2022-02-10T10:12:53       0     200
2022-02-10T10:12:53       0     220
2022-02-10T10:12:53       0     240
2022-02-10T10:12:53       0     260
2022-02-10T10:12:53       0     280
2022-02-10T10:12:53       0     300
2022-02-10T10:12:53       0     300
Started at 2022-02-10T10:12:53, ended at 2022-02-10T10:12:53
Source: A=UTF8,D=destination,P=33106,h=127.0.0.1,p=...,t=user,u=root
SELECT 300
INSERT 0
DELETE 300
Action             Count       Time        Pct
commit                16     0.0443      74.82
bulk_deleting         15     0.0048       8.07
select                16     0.0037       6.32
other                  0     0.0064      10.79

4.4 表自增字段处理

说明:
默认情况下,pt-archiver工具在进行表数据归档或是清除时,通过添加WHERE子句条件限制具有AUTO_INCREMENT属性字段所对应的数据行操作,这是为了在数据库重启之后,之前AUTO_INCREMENT对应的值还可以使用(),但这会造成归档数据少一条或是清除数据少一条的情况。

5. 总结

  1. 用于批量归档大数据表中的部分冷数据,到其他MySQL实例。
  2. 注意要求表存在auto_increment。
  3. 熟悉pt-archiver存在的bug,并有意规避。
  4. 在非生产环境进行测试(同数据库版本,同库同表结构)。
  5. 生产环境做好备份并验证数据(可监控、可灰度、可回滚)。

参考链接:
H_Johnny 的 Percona-Toolkit 之 pt-archiver 总结 ,写的很不错。

Percona 的 pt-archiver官方文档

MySQL-运维工具 pt-archiver数据归档工具相关推荐

  1. linux运维笔记:Rsync数据同步工具

    linux运维笔记:Rsync数据同步工具 1-Rsync简介 Rsync英文全称是Remote synchronization,Rsync具有可以使本地和远程两台主机之间的数据快速复制和同步镜像.远 ...

  2. mysql 回滚_一个集审核、执行、备份及生成回滚语句于一身的MySQL运维工具

    goInception 一个集审核.执行.备份及生成回滚语句于一身的MySQL运维工具, 通过对执行SQL的语法解析,返回基于自定义规则的审核结果,并提供执行和备份及生成回滚语句的功能 架构图 使用方 ...

  3. 数据归档工具pt-archiver原理研究与使用

    1.介绍 之前处理mysql历史数据归档,直接写存储过程实现的(<mysql历史数据自动归档>),换新东家后,还是决定研究下主流的pt-archiver并实施. mysql除了社区版,还有 ...

  4. mysql运维备份_MySQL运维经验

    原标题:MySQL运维经验 1. 概要 每台机器都使用多实例的模型. 每个机器放多个实例,每个实例放多个DB. 多实例之间没有进行资源隔离,这么做是让每个实例都能发挥最大性能. 目前大部分核心业务已切 ...

  5. MySQL 运维 - 从零开始学习 | 超详细

    MySQL 运维 - 从零开始学习 一.数据库类型 ► 常见的数据库类型 二.数据库管理系统 DBMS ►数据库系统 ►关系型数据库 ►非关系型数据库 Not Only SQL 三.安装MySQL ► ...

  6. 猿创征文 | DevOps运维的10个日常使用工具分享

    猿创征文 | DevOps运维的10个日常使用工具分享 一.DevOps介绍 1.DevOps的简介 2.个人分享的10个工具导航 二.jenkins 1.jenkins介绍 2.jenkins的优点 ...

  7. Mysql运维常用命令回顾整理

    一.前景 Mysql作为开源数据库的中坚力量之一,虽然目前已被甲骨文收购,面临闭源风险,但是mysql扔是我们运维工作中最常面对的工作,那如何做好mysql运维工作,甚至做好mysql的基础运维,都是 ...

  8. MySQL运维(二)MySQL分库分表概念及实战、读取分离详解

    MySQL运维(二)MySQL分库分表详解.读取分离详解 1.MySQL分库分表相关概念 1.1 分库分表概念 1.1.1 分库的原因 分库:就是一个数据库分成多个数据库,部署到不同机器. 如果业务量 ...

  9. mysql系列问答题_(2)MySQL运维基础知识面试问答题

    面试题001:请解释关系型数据库概念及主要特点? 面试题002:请说出关系型数据库的典型产品.特点及应用场景? 面试题003:请解释非关系型数据库概念及主要特点? 面试题004:请说出非关系型数据库的 ...

  10. 20个MySQL运维案例,请查收!

    墨墨导读:日常MySQL运维中,会遇到各种各样的问题,下面分享二十个MySQL运维案例,附有问题的分析和解决办法,希望你遇到同样的问题的时候,可以淡定地处理. 数据技术嘉年华,十周年盛大开启,点我立即 ...

最新文章

  1. C# Socket 入门5 UPD 结构体 与 C++ 通信
  2. Eclipse常用的高效插件
  3. 超基础的Android studio的安装教程
  4. chroot环境怎么重启linux,linux下简易chroot环境的塔建
  5. Linux Shell常用技巧(四)
  6. 论述HTML5平台的若干重要特性
  7. python timer 死掉_Python timer定时器两种常用方法解析 Python中如何在一段时间后停止程序...
  8. 微课|中学生可以这样学Python(6.3节):变量作用域
  9. 第三篇:白话tornado源码之请求来了
  10. 径向涡轮膨胀机行业调研报告 - 市场现状分析与发展前景预测
  11. Python开发工程师常用开发工具
  12. memcached—认识Memcache
  13. vue 地址区域选择组件
  14. 联想服务器TS540装系统蓝屏,联想装win7蓝屏0x000000a5超详细图文解决方案
  15. 起重机液压控制系统实训QY-JXSX01
  16. 解决在mysql官网下载慢的问题
  17. position之relative
  18. server酱php推送代码,多种语言调用Server酱推送微信模板消息
  19. ZT “樱花小萝莉”走红网络 网友:好想生个女儿
  20. ex.php,Exphp代码走读(二)

热门文章

  1. 自媒体文章标题的大坑,难怪你写的文章没有推荐
  2. 使用Vim/Neovim编辑二进制文件
  3. Java基础知识和进阶
  4. cc2530协调器向终端发信息
  5. matlab小波变换、离散小波变换函数使用
  6. Oracle 多行显示在一行详解(listagg)
  7. python模拟点击屏幕ios_python模拟点击可以在ios中实现吗?
  8. 云技术:弹性计算ECS
  9. Java服务端支付宝对接(详细)
  10. deepin有线网卡无法连接网络