前面介绍mysqldump备份方式是采用逻辑备份,其最大的缺陷就是备份和恢复速度都慢,对于一个小于50G的数据库而言,这个速度还是能接受的,但如果数据库非常大,那再使用mysqldump备份就不太适合了。而使用lvm快照功能对数据库进行备份,可以实现几乎热备的功能,但备份过程较为复杂,不过现在倒是有个工具mylvmbackup可以实现自动化备份。

前面我们也说道,使用物理备份时最快的,那有没有办法实现物理热备呢?

目前主流的有两个工具可以实现热备:ibbackup和xtrabackup;ibbackup是商业软件,没服务器授权为5000美元,非常昂贵。而xtrabackup功能比ibbackup还要强大,但却是开源的。因此我们这里就来介绍xtrabackup的使用。

Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具。特点:

(1)备份过程快速、可靠;

(2)备份过程不会打断正在执行的事务;

(3)能够基于压缩等功能节约磁盘空间和流量;

(4)自动实现备份检验;

(5)还原速度快;

下面是Percona官方对ibbackup和xtrabackup的功能对比:

Feature

Percona XtraBackup

MySQL Enterprise Backup

(InnoDB Hot Backup)

License

GPL

Proprietary

Open source

Non-blocking

InnoDB backups

MyISAM backups

Compressed backups

Partial backups

Throttling

Point-in-time recovery support

Incremental backups

Parallel backups

Streaming backups

Parallel compression

LRU backups

OS buffer optimizations

Export individual tables

Restore tables to a different server

Analyze data & index files

Familiar command-line behavior

[1]MyISAM backups require a table lock.

[2]Percona XtraBackup performs throttling based on the number of IO operations per second. MySQL Enterprise Backup supports a configurable sleep time between operations.

[3]Percona XtraBackup tunes the operating system buffers to avoid swapping. See the documentation.

[4]Percona XtraBackup is linked against the MySQL client libraries, so it behaves the same as standard MySQL command-line programs. MySQL Enterprise Backup has its own command-line and configuration-file behaviors.

一、下载和安装

XtraBackup现在最新版本为2.1.5,官方也提供了2.0的版本可供下载,官方链接地址:http://www.percona.com/software/percona-xtrabackup;可以下载源码编译安装,也可以下载适合的RPM包或使用yum进行安装。由于没有需要特殊定制的,因此建议直接使用RPM安装即可。

安装方法一:

下载RPM安装包:

安装依赖:

[root@localhost ~]# yum install -y perl-DBD-MySQL perl-DBI  perl-Time-HiRes libaio*

安装:

[root@localhost ~]# rpm -ivh percona-xtrabackup-2.1.5-680.rhel6.x86_64.rpm

Preparing...                      ########################################### [100%]

1:percona-xtrabackup     ########################################### [100%]

安装方法二:

安装percona源:

[root@localhost ~]# rpm -Uhv http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm

使用yum安装percona-xtrabackup:

[root@localhost ~]# yum -y install percona-xtrabackup

查看安装结果:

[root@localhost ~]# rpm -qa |grep  xtrabackup

percona-xtrabackup-2.1.5-680.rhel6.x86_64

[root@localhost ~]# rpm -ql percona-xtrabackup-2.1.5-680.rhel6.x86_64

/usr/bin/innobackupex

/usr/bin/innobackupex-1.5.1

/usr/bin/xbcrypt

/usr/bin/xbstream

/usr/bin/xtrabackup

/usr/bin/xtrabackup_55

/usr/bin/xtrabackup_56

/usr/share/doc/percona-xtrabackup-2.1.5

/usr/share/doc/percona-xtrabackup-2.1.5/COPYING

Xtrabackup中主要包含两个工具:

xtrabackup:是用于热备份innodb, xtradb表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;

innobackupex:是将xtrabackup进行封装的perl脚本,提供了备份myisam表的能力。

二、使用xtrabackup实现对MySQL的备份:

2.1 完全备份:

基本语法:

# innobackupex --user=DBUSER --password=DBUSERPASS  /path/to/BACKUP-DIR/

注意,如果只想该命令时报如下这样的错误:

Can't load '/usr/local/lib64/perl5/auto/DBD/mysql/mysql.so' for module DBD::mysql: libmysqlclient.so.18: 无法打开共享对象 at /usr/bin/innobackupex line 18

需要拷贝libmysqlclient.so.18至/usr/lib64:

[root@localhost ~]# cp /usr/local/mysql/lib/libmysqlclient.so.18 /usr/lib64/

实例:

备份后的文件:

在备份的同时,备份数据会在备份目录下创建一个以当前日期时间为名字的目录存放备份文件:

各文件说明:

(1)xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

(3)xtrabackup_binlog_pos_innodb —— 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf —— 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

另外还需注意:备份数据库的用户需要具有相应权限,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

mysql> CREATE USER ‘bkpuser'@'localhost’ IDENTIFIED BY ‘newpasswd’;

mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM ‘bkpuser’;

mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO ‘bkpuser’@’localhost’;

mysql> FLUSH PRIVILEGES;

2.2 准备(prepare)一个完全备份

一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:

# innobackupex --apply-log  /path/to/BACKUP-DIR

如果执行正确,其最后输出的几行信息通常如下:

在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。

2.3 对完全备份的后数据库更改进行二进制日志增量备份:

2.3.1 查看完全备份时日志位置:

[root@localhost 2013-10-04_20-31-56]# cat xtrabackup_binlog_info

mysql-bin.000005    107

2.3.2 模拟数据库修改:

mysql> use jiaowu;

Database changed

mysql> INSERT INTO tutors (Tname) VALUES ('stu01');

Query OK, 1 row affected (0.11 sec)

mysql> INSERT INTO tutors (Tname) VALUES ('stu02');

Query OK, 1 row affected (0.00 sec)

2.3.3 增量备份二进制文件:

[root@localhost 2013-10-04_20-31-56]# mysqlbinlog --start-position=107 /data/mysql/mysql-bin.000005 >`date +%F`.sql

注:--start-position=107 可以不指定,因为107是一个日志的默认起始位置。

3 还原数据库:

3.1 模拟数据库损坏:

与之前其他备份测试一样,我这里直接使用删除数据目录文件来模拟损坏。

[root@localhost ~]# cd /data/mysql/

[root@localhost mysql]# ls

ibdata1      jiaowu                     my.cnf            mysql-bin.000002  mysql-bin.000005    test

ib_logfile0  localhost.localdomain.err  mysql             mysql-bin.000003  mysql-bin.index

ib_logfile1  localhost.localdomain.pid  mysql-bin.000001  mysql-bin.000004  performance_schema

[root@localhost mysql]# rm -rf *

3.2 还原完全备份:

innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。

3.2.1 还原数据库语法:

# innobackupex --copy-back  /path/to/BACKUP-DIR

如果执行正确,其输出信息的最后几行通常如下:

innobackupex: Starting to copy InnoDB log files

innobackupex: in '/backup/2012-04-07_08-17-03'

innobackupex: back to original InnoDB log directory '/mydata/data'

innobackupex: Finished copying back files.

120407 09:36:10  innobackupex: completed OK!

请确保如上信息的最行一行出现“innobackupex: completed OK!”。

3.2.2 修改还原后的数据目录权限:

[root@localhost mysql]# pwd

/data/mysql

[root@localhost mysql]# ll

总用量 28740

-rw-r--r--. 1 root root        0 10月  4 21:27 05.sql

-rw-r--r--. 1 root root     2207 10月  4 21:27 2013-10-04.sql

-rw-r--r--. 1 root root 18874368 10月  4 21:27 ibdata1

-rw-r--r--. 1 root root  5242880 10月  4 21:27 ib_logfile0

-rw-r--r--. 1 root root  5242880 10月  4 21:27 ib_logfile1

drwxr-xr-x. 2 root root     4096 10月  4 21:27 jiaowu

drwxr-xr-x. 2 root root     4096 10月  4 21:27 mysql

drwxr-xr-x. 2 root root     4096 10月  4 21:27 performance_schema

drwxr-xr-x. 2 root root     4096 10月  4 21:27 test

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:

[root@localhost mysql]# chown -R mysql.mysql ./*

[root@localhost mysql]# ll

总用量 28740

-rw-r--r--. 1 mysql mysql        0 10月  4 21:27 05.sql

-rw-r--r--. 1 mysql mysql     2207 10月  4 21:27 2013-10-04.sql

-rw-r--r--. 1 mysql mysql 18874368 10月  4 21:27 ibdata1

-rw-r--r--. 1 mysql mysql  5242880 10月  4 21:27 ib_logfile0

-rw-r--r--. 1 mysql mysql  5242880 10月  4 21:27 ib_logfile1

drwxr-xr-x. 2 mysql mysql     4096 10月  4 21:27 jiaowu

drwxr-xr-x. 2 mysql mysql     4096 10月  4 21:27 mysql

drwxr-xr-x. 2 mysql mysql     4096 10月  4 21:27 performance_schema

drwxr-xr-x. 2 mysql mysql     4096 10月  4 21:27 test

3.2.3 启动MySQL:

[root@localhost mysql]# service mysqld start

Starting MySQL (Percona Server)... SUCCESS!

3.2.4 验证还原后的数据:

3.3 还原增量备份:

3.3.1 还原增量备份:

为了防止还原时产生大量的二进制日志,在还原时可临时关闭二进制日志后再还原:

mysql> set sql_log_bin=0;

Query OK, 0 rows affected (0.00 sec)

mysql> SOURCE /data/backup/2013-10-04_20-31-56/2013-10-04.sql

3.3.2 重新启动二进制日志并验证还原数据:

mysql> set sql_log_bin=1;

Query OK, 0 rows affected (0.00 sec)

4 使用innobackupex进行增量备份

前面我们进行增量备份时,使用的还是老方法:备份二进制日志。其实xtrabackup还支持进行增量备份。

每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。

4.1 基本语法:

增量备份前应进行一次完全备份。增量备份语法如下:

innobackupex --incremental /backup --incremental-basedir=BASEDIR

其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。

需要注意的是,增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。

为了演示,我们先进行一次完全备份,并在完全备份后对数据做些修改:

[root@localhost ~]# innobackupex --user=root /data/backup

mysql> use jiaowu;

Database changed

mysql> INSERT INTO tutors (Tname) VALUES ('stu03');

Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO tutors (Tname) VALUES ('stu04');

Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO tutors (Tname) VALUES ('stu05');

Query OK, 1 row affected (0.01 sec)

进行增量备份:

[root@localhost ~]# innobackupex --incremental /data/backup --incremental-basedir=/data/backup/2013-10-04_21-45-03/

4.2 准备:

“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:

(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。

(2)基于所有的备份将未提交的事务进行“回滚”。

于是,操作就变成了,执行完全备份的redo:

# innobackupex --apply-log --redo-only BASE-DIR

接着执行第一个增量:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

而后是第二个增量:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作。

4.3 还原:

在准备步骤完成后,还原时只需要还原完全备份即可,步骤后同3.2,这里不再演示。

# innobackupex --copy-back  /path/to/BACKUP-DIR

5、Xtrabackup的“流”及“备份压缩”功能

Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用--stream选项即可。如:

# innobackupex --stream=tar  /backup | gzip > /backup/`date +%F_%H-%M-%S`.tar.gz

甚至也可以使用类似如下命令将数据备份至其它服务器:

# innobackupex --stream=tar  /backup | ssh user@www.magedu.com  "cat -  > /backups/`date +%F_%H-%M-%S`.tar"

此外,在执行本地备份时,还可以使用--parallel选项对多个文件进行并行复制。此选项用于指定在复制时启动的线程数目。当然,在实际进行备份时要利用此功能的便利性,也需要启用innodb_file_per_table选项或共享的表空间通过innodb_data_file_path选项存储在多个ibdata文件中。对某一数据库的多个文件的复制无法利用到此功能。其简单使用方法如下:

# innobackupex --parallel  /path/to/backup

同时,innobackupex备份的数据文件也可以存储至远程主机,这可以使用--remote-host选项来实现:

# innobackupex --remote-host=root@www.magedu.com  /path/IN/REMOTE/HOST/to/backup

6、导入或导出单张表

默认情况下,InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植,即便使用了innodb_file_per_table选项。而使用Xtrabackup工具可以实现此种功能,不过,此时需要“导出”表的mysql服务器启用了innodb_file_per_table选项(严格来说,是要“导出”的表在其创建之前,mysql服务器就启用了innodb_file_per_table选项),并且“导入”表的服务器同时启用了innodb_file_per_table和innodb_expand_import选项。

6.1 “导出”表

导出表是在备份的prepare阶段进行的,因此,一旦完全备份完成,就可以在prepare过程中通过--export选项将某表导出了:

# innobackupex --apply-log --export /path/to/backup

此命令会为每个innodb表的表空间创建一个以.exp结尾的文件,这些以.exp结尾的文件则可以用于导入至其它服务器。

6.2“导入”表

要在mysql服务器上导入来自于其它服务器的某innodb表,需要先在当前服务器上创建一个跟原表表结构一致的表,而后才能实现将表导入:

mysql> CREATE TABLE mytable (...)  ENGINE=InnoDB;

然后将此表的表空间删除:

mysql> ALTER TABLE mydatabase.mytable  DISCARD TABLESPACE;

接下来,将来自于“导出”表的服务器的mytable表的mytable.ibd和mytable.exp文件复制到当前服务器的数据目录,然后使用如下命令将其“导入”:

mysql> ALTER TABLE mydatabase.mytable  IMPORT TABLESPACE;

7、使用Xtrabackup对数据库进行部分备份

Xtrabackup也可以实现部分备份,即只备份某个或某些指定的数据库或某数据库中的某个或某些表。但要使用此功能,必须启用innodb_file_per_table选项,即每张表保存为一个独立的文件。同时,其也不支持--stream选项,即不支持将数据通过管道传输给其它程序进行处理。

此外,还原部分备份跟还原全部数据的备份也有所不同,即你不能通过简单地将prepared的部分备份使用--copy-back选项直接复制回数据目录,而是要通过导入表的方向来实现还原。当然,有些情况下,部分备份也可以直接通过--copy-back进行还原,但这种方式还原而来的数据多数会产生数据不一致的问题,因此,无论如何不推荐使用这种方式。

7.1 创建部分备份

创建部分备份的方式有三种:正则表达式(--include), 枚举表文件(--tables-file)和列出要备份的数据库(--databases)。

7.1.1 使用--include

使用--include时,要求为其指定要备份的表的完整名称,即形如databasename.tablename,如:

# innobackupex --include='^mageedu[.]tb1'  /path/to/backup

7.1.2 使用--tables-file

此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称;如:

# echo -e 'mageedu.tb1\nmageedu.tb2' > /tmp/tables.txt

# innobackupex --tables-file=/tmp/tables.txt  /path/to/backup

7.1.3 使用--databases

此选项接受的参数为数据名,如果要指定多个数据库,彼此间需要以空格隔开;同时,在指定某数据库时,也可以只指定其中的某张表。此外,此选项也可以接受一个文件为参数,文件中每一行为一个要备份的对象。如:

# innobackupex --databases="mageedu testdb"  /path/to/backup

7.2 整理(preparing)部分备份

prepare部分备份的过程类似于导出表的过程,要使用--export选项进行:

# innobackupex --apply-log --export  /pat/to/partial/backup

此命令执行过程中,innobackupex会调用xtrabackup命令从数据字典中移除缺失的表,因此,会显示出许多关于“表不存在”类的警告信息。同时,也会显示出为备份文件中存在的表创建.exp文件的相关信息。

7.3 还原部分备份

还原部分备份的过程跟导入表的过程相同。当然,也可以通过直接复制prepared状态的备份直接至数据目录中实现还原,不要此时要求数据目录处于一致状态。

xtrbackup更换数据库_使用xtrabackup进行MySQL数据库备份 | 旺旺知识库相关推荐

  1. 红帽下安装mysql数据库_[原创]RedHat 安装MySQL数据库

    朋友购买了阿里云的服务器,服务器上自带有CentOS操作系统,但是开发软件需要自己安装,接下来将介绍本地RedHat Linux 5.10虚拟机上搭建Mysql数据库. 一.软件准备 (1)jdk-6 ...

  2. mysql使用已有的数据库_使用SQL操作MySQL数据库

    用SHOW显示已有的数据库 句法:SHOW DATABASES [LIKE wild] 如果使用LIKE wild部分,wild字符串可以是一个使用SQL的"%"和"_& ...

  3. vb连接云mysql数据库_用vb链接mysql数据库

    MySQL字符集不一致的解决办法总结 这阵子忙着把数据库从MS SQL数据库改成MySQL数据库,简直过着非人的生活! 再怎么忙,还是想做做笔记,绝不允许自己把一个错误重犯二次.OK,言归正传... ...

  4. 如何移植mysql数据库_如何把本地MySql数据库移植到远程服务器上

    用dedecms做了一个女性网站,是仿爱丽女人网的.为了在本地测试,就要添加分类栏目,为了看首页和列表页面的效果,还得在网上采集大量的各个分类的内容.这样下来几十个栏目每栏目几十条信息,信息一下就是几 ...

  5. python网站用什么数据库_使用python读取mysql数据库并进行数据的操作

    简介:(一)环境的配置使用python调用mysql数据库要引进一些库.目前我使用的python版本是python3.6.引进库为pymysql其他对应的库可以有以下选择: mysqldb,oursq ...

  6. java 读取mysql数据库_原生Java操作mysql数据库过程解析

    这篇文章主要介绍了原生Java操作mysql数据库过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.引入数据库驱动的jar包 以通过mav ...

  7. dos创建mysql数据库_用命令创建MySQL数据库

    一.连接MYSQL 格式: mysql -h主机地址 -u用户名 -p用户密码 1. 连接到本机上的MYSQL. 首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u roo ...

  8. 安装 mysql 数据库_小水谈Mysql数据库---Mysql安装

    介绍: MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好 ...

  9. java创建数据库mysql数据库_用Java创建MySQL数据库

    为了使事情变得更简单,您可以使用NetBeans 6.5,它使设置SQL数据库变得更加容易.我现在正在使用它们,它是GUI布局和数据库连接的救命稻草.下面是一些关于如何从NetBeans连接到MySQ ...

最新文章

  1. 分区字段必须包含在主键字段_24 个必须掌握的数据库面试问题!
  2. SAP 序列号与库存关联起来?
  3. 量化集体行为特刊:信息论为量化集体性提供形式化框架
  4. VC++开发一个简易图片浏览器 - 含目录浏览功能
  5. Google Earth Pro 模拟飞行 分享
  6. Python中map和reduce函数?
  7. python max函数_Python max内置函数详细介绍
  8. 【javascript】操作符:一元操作符
  9. 29岁“退休程序员”郭宇:有钱的人不一定自由,自由的人不一定有钱
  10. 2020-11-25 阿里云CentOS linux源配置脚本 https://mirrors.aliyun.com/repo/
  11. [转载] Python程序将十进制转换为二进制,八进制和十六进制
  12. ADRC自抗扰控制学习
  13. 水晶报表10.0企业版下载地址及注册码
  14. 三维坐标系旋转的顺时针_逆时针问题
  15. python水浒传名字次数_《水浒传》中108个好汉的姓名及绰号!要按顺序!
  16. 医院预约挂号系统使用说明
  17. 微信吸粉实战二:腾讯新闻
  18. 基于Arduino的多功能智能交通信号灯的设计与实现 ---------对盲人语音播报,红灯结束时铃声提醒,信号灯倒计时和闯红灯语音劝阻
  19. 面试官:来考考你几道常见的MySQL题目吧
  20. mysql内幕微盘_MySQL核心内幕(祝定泽、张海、黄建昌) PDF 扫描版[29M]

热门文章

  1. 去除文本框边侧滚动条
  2. XMC外设学习之USIC
  3. Lvs+keepalived+Nginx实现服务器一主一备(高可用)
  4. 部署一个合约花费了3.5ETH - GasLimit和GasPrice谨慎设值区间
  5. 注意力机制——Recurrent Attention Model(RAM)
  6. 家用洗地机哪个品牌好?清洁力强的洗地机品牌推荐
  7. 图解解析 + 代码实现:带你手撕冒泡、选择、插入、希尔排序。
  8. 【XJOI】种花 flower
  9. Unity Shader动画-做捕鱼达人效果
  10. 31条指令单周期cpu设计(Verilog)-(六)指令操作时间表设计