jenkins持续集成二——spring boot集成设置

前面安装好了环境,这一篇主要讲下设置

系统管理->管理插件

image_thumb9

以下是默认安装插件之外,需要额外安装的插件。

系统管理->全局工具配置

image_thumb4

配置JDK

image_thumb1

配置git

image_thumb3

配置maven

image_thumb7

系统管理->系统设置

image_thumb11

这里主要需要对jenkins 将集成应用通过ssh部署到应用服务器的SSH 连接配置

示例如下,同时需要了解SSH免密登录相关内容。

image_thumb14

SSH免密登录

#ubuntu环境在客户机器上生成密钥对,密钥会生成在~/.ssh/目录下
ssh-keygen -t rsa

生成多机器不同密钥对免密登录配置

#配置多远程机器不同密钥的配置,在~/.ssh/ 生成config
touch config

示例配置如下

image_thumb16

将公钥拷贝到远程机器上

#ssh-copy-id [-i [identity_file]] [user@]machine
ssh-copy-id -i id_rsa_git git@127.0.0.1
#该公钥信息会记录到git 服务器的~/.ssh/authorized_keys 文件

测试

ssh git@git #or ssh git@127.0.0.1

Credentials

从git 拉取代码,使用SSH 信用连接,设置 Credentials,添加git 相关的SSH 连接认证,如下图示例:

image_thumb20

Maven 构建项目配置

新建按钮如下

image_thumb18

配置

git源

image_thumb22

构建触发

image_thumb24

10分钟构建一次

自动部署

image_thumb26

文件存档

image_thumb28

jenkins持续集成(一)-基础安装设置

jenkins  作为持续集成现在用得越来越广,以前都是公司直接配置好了用上就好,现在就按部就班从0开始弄个持续集成环境吧。


jenkins

安装

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

启动

启动:  
sudo service jenkins start  
停止:  
sudo service jenkins stop

路径

log 路径:/var/log/jenkins/jenkins.log
jenkins的home路径:/var/lib/jenkins
端口号修改路径:sudo vi /etc/default/jenkins

初始化

通过浏览器就可以访问Jenkins了。比如我的地址:http://192.168.2.126:7777/,按照页面提示安装插件及设置管理员账户密码。

image

为了确保Jenkins的安全,将管理员的密码写入文件,需要复制到下面的文本框做验证。

/var/lib/jenkins/secrets/initialAdminPassword

然后,到了选择插件的界面,通过附加功能扩展Jenkins可以支持许多不同的需求。

image

image

image

image

git

安装

安装
sudo apt-get install git
#添加用户
useradd git
#配置SSH登录
cd ~
mkdir .ssh 
cd .ssh
touch authorized_keys
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
rm ~/id_rsa.pub
#授权
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

使用

#新建目录
mkdir   zwr
#新建初始化仓库
git init --bare test.git

Maven

安装

方式一

#下载
wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
#解压
tar -xzf apache-maven-3.3.9-bin.tar.gz
#移动
mv apache-maven-3.3.9  /usr/share/maven
#设置环境变量
vim /etc/profile
#环境变量内容
M2_HOME=/usr/share/maven
CLASSPATH=$CLASSPATH:$M2_HOME/lib
PATH=$PATH:$M2_HOME/bin
export   PATH    CLASSPATH   M2_HOME
#生效
source /etc/profile

方式二

apt-get install -y maven
mvn -version

fabric简介

1.设计目的

2.基本架构流程

3.基本组成介绍

4.接口

5.示例

设计目的范围

是一个企业级联盟链,主要考虑商业应用对安全、隐私、监管、审计、性能的需求,提高准入门槛,增加了安全、隐私、可监管审计等商业特性,是区块链技术在商业领域的应用探索。

基本框架流程

image

 

 

逻辑概念:客户端,会员服务,peer节点(背书节点,确认节点,非交易节点),共识节点

CA服务:

上图中最左边是证书服务系统,主要提供会员注册和证书颁发功能,Fabric系统的参与方都必须经过授权,比如Orderer、Peer、Client等都需要拥有受信任的证书。证书一方面用于系统接入,另一方面用于交易签名。所以统一的证书服务非常重要。会员证书又分为注册证书和交易证书,注册证书与会员信息关联在一起,用于标识会员的身份,在必要的时候,还可以支持监管和审计;交易证书用于交易签名,之所以交易要用不同的证书,是为了避免会员的个人信息和交易信息被泄露,比如交易内容或者多笔交易之间的关联关系等,另外交易证书可以申请多份,甚至可以为每一笔交易申请一份交易证书。

client:经过CA认证的业务应用客户端

PEER:

背书节点:使用chaincode预交易,并应用背书策略对交易签名背书。

确认节点:从共识节点接收到块后,对块数据进行校验,然后写入区块中,交易状态信息记录入状态数据库,交易可能失败,对块交易记录。(特别是同一资源的高并发处理,及其容易交易失败,虽然交易数据得到了共识,但是业务的强一致性还是会因为分布式后没法得到保障)

共识节点:对交易进行排序共识,完成后推送到相应的节点

共识网络:共识节点组成共识网络

多链:通过建立不同通道,将数据隔离,加入通道的节点与共识节点共同组成一个链,共识网络对不同通道生成不同的块。

基本组件及特点

组件化,可扩展,可拔插

CA服务:支持PKI系列的证书

共识网络:支持KAFKA,PBFT,SBFT

账本:区块文件 & 状态库 :leveldb,couchdb

链码(合约):可用go,java,nodejs编写,运行在docker容器中,合约就两个接口,init+invoke,用户合约不能创建新合约(由系统生命周期合约统一管理)。0.6版本不是跨链调用合约,现在1.0版本没试过。

底层通信:grpc+pb

接口

0.6版本可直接用restful进行接口调试

1.0 版本我们看流程,客户端需要两段式的递交信息,所以目前是不支持使用postman这种http.restful 进行接口调试,只能应用SDK或封装好的client中进行。

示例

部署示例:理论上支持全平台,但是还是直接在ubuntu上会比较轻松,需要golang,docker,docker-compase,

开发示例:之前都在windows+vagant 虚拟化开发环境,

安装测试示例:

物理架构节点:

1cli+4peers+1orderer

逻辑

2个组织,每个组织2个节点,加入一个通道

步骤

组网:

1.编写配置文件,使用cryptogen 生成相应证书。

2.建立通道,将节点加入通道

在网络上测试:

1.创建合约,并在特定链上实例化一个合约

2.可进行交易

测试需要在cli上操作:

创建合约:

peer chaincode install -n zwrcc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/zwr

实例化合约:

peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C mychannel -n zwrcc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","zwr", "1000", "mmm","2000"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

查询:

peer chaincode query -C mychannel -n zwrcc -c '{"Args":["query","zwr"]}'

交易:

peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C mychannel -n zwrcc -c '{"Args":["invoke","mmm","zwr","100"]}'

ethereum钱包交易

前面一篇已经把私有链部署起来,如果要开发创新创新场景的应用,一般是需要后台智能合约及前端展示,作为大众用户,一般不会去关心后台啥啥的,也不会去下载个什么专业的桌面钱包来管理“合约”相关交易,并且现在一般手机应用也是混合居多,所以我们现在就直接基于JS把Web前端开发做个示例。后台智能合约开发后续再详细讲下。

链服务端

要直接操作以太坊链,服务端需要启动一个链的节点,并开放RPC端口供客户端调用,开启命令为进入geth

[bath]admin.startRPC( ‘192.168.226.88’,’8545′,’*’)[/bath]

web3.js

以太坊区块链 提供了jason的数据交互格式及httprpc 的访问协议供前端应用的开发,并且封装到了web3.js.

步骤

1.加载初始化web3.js,并连接到后端rpc端口地址

1) 引入依赖
<script type="text/javascript" src=".../web3.min.js"></script>

2) 创建实例
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

2.使用web3使用各个接口进行交易操作

  • 同步调用
    var balance = web3.eth.getBalance(address);
  • 异步回调
    web3.eth.getBalance(address, function(error, result){...});

4) 批量调用
var batch = web3.createBatch(); batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback)); batch.add(web3.eth.contract(abi).at(address).balance.request(address, callback2)); batch.execute();

web3.js 接口用法详见https://github.com/ethereum/wiki/wiki/JavaScript-API

web3.js 主要针对区块链交易等,而还有一个js库ethereumjs-wallet提供钱包功能,如果要做在线钱包功能可以使用该库。

 

该地址提供了ethereum 不同JS功能相关库信息资料http://ethereumjs.github.io/

ethereum私有链部署

本篇主要给开发人员阅读,要了解以太坊,区块链等概念基本知识,网络上搜索下就好。本篇进行私有链部署,当然你也可以直接在以太坊的测试链上进行,就省去私有链部署过程。

工具

我们需要如下客户端:

geth(以太坊节点客户端):

通过geth可以加入一个以太坊链,也可以建立一个自己的私有链然后加入。

mist(依托geth的图形化钱包管理客户端):

可在钱包中进行账户管理及合约操作并测试

链元数据(创世块)

新建一个文件genesis.json内容如下:

{ "alloc": { "bd2d69e3e68e1ab3944a865b3e566ca5c48740da": { "balance": "4000000000000000000000000000000" }, "ca9f427df31a1f5862968fad1fe98c0a9ee068c4": { "balance": "5000000000000000000000000000000" } }, "nonce": "0x0000000000000042", "difficulty": "0x060000", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", "timestamp": "0x00", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "missummerwillenyuan", "gasLimit": "0x4c4b40" }

 

参数

描述

mixhash

与nonce配合用于挖矿,由上一个区块的一部分生成的hash。注意他和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。

nonce

nonce就是一个64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。

difficulty

设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度

alloc

用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。

coinbase

矿工的账号,随便填

timestamp

设置创世块的时间戳

parentHash

上一个区块的hash值,因为是创世块,所以这个值是0

extraData

附加信息,随便填,可以填你的个性信息

gasLimit

该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。

步骤

1.使用命令行通过geth 设置创世区块及区块链保存目录

[bath]geth –datadir “C:\Users\zhouwr\AppData\Roaming\Ethereum\willenchain” init genesis.json [/bath]

2.通过geth 启动该区块链

[bath]geth –identity “willenetherum” –rpc –rpccorsdomain “*” –datadir “C:\Users\zhouwr\AppData\Roaming\Ethereum\willenchain” –port “30303” –rpcapi “db,eth,net,web3″ –networkid 95518 console[/bath]

上面的步骤一个区块链已经创建成功,那么我们加入账号使用他们

账号

添加账号,当然测试用,我们就把创始分配有以太币的账号加进来

[bath]geth –datadir “C:\Users\zhouwr\AppData\Roaming\Ethereum\willenchain”  account import ca9f427df31a1f5862968fad1fe98c0a9ee068c4.key[/bath]

使用如下脚本查看账号

[bath]geth -datadir “C:\Users\zhouwr\AppData\Roaming\Ethereum\willenchain” account list[/bath]

或者启动区块链后使用如下命令查看账号:

[bath]eth.accounts[/bath]

当然同时我们可以使用图形化钱包来查看账号

参数

描述

identity

区块链的标示,随便填写,用于标示目前网络的名字

init

指定创世块文件的位置,并创建初始块

datadir

设置当前区块链网络数据存放的位置

port

网络监听端口

rpc

启动rpc通信,可以进行智能合约的部署和调试

rpcapi

设置允许连接的rpc的客户端,一般为db,eth,net,web3

networkid

设置当前区块链的网络ID,用于区分不同的网络,是一个数字

console

启动命令行模式,可以在Geth中执行命令

nodiscover

禁止被网络中其它节点发现,需要手动添加该节点到网络

verbosity

打印详细的日志信息

图型化钱包及交易

可以启动钱包Ethereum-Wallet-win64-0-8-5了,我们可以看到有个主账户并有好多ether,现在我们在钱包中新建一个账户,然后主账户转账1000ether给新建的账户,输入密码之后我们看到状态是确认中,那么我们需要在geth的命令行界面启动挖矿命令:miner.start(),将该笔交易记录到区块中,因为我们设置的挖矿难度很低,所以开启后看到挖出几个区块之后我们要停止挖矿,miner.stop(),不然会浪费好多区块,再回到图形化钱包,我们已经看到新账户已经到账ether 了。

网络

使用VirtualBox创建以太windows 7虚拟机,然后重复第一个节点的创建步骤在虚拟机上部署geth和以太坊钱包,同样需要初始化文件hdgenesis.json(同一个文件拷贝一份),并运行初始化命令,然后再运行启动命令,启动之后运行admin.nodeInfo.enode命令获取新节点的enode信息,然后在第一个节点上运行 admin.addPeer(enode URL)来添加新节点,注意将enode URL中[::]替换为新节点的IP地址,添加成功后运行admin.peers命令即可查看对等节点信息。

至此,一套基于geth的本地简单私有网络创建完成,可以在这套环境上进行简单的智能合约创建和测试。

智能合约

基本上,现今我们的应用创新场景有如下可行的:

底层创新:基本上是区块链算法上的创新,如修改一下共识机制之类的创新。

平台创新:Baas,区块链即服务,就是能够帮助企业快速部署一条私有链,将链作为服务提供给需要的企业。

场景创新:再一条固定的以太坊区块链上,将可行的应用场景引入进来,解决一些问题,比如信息保密需求,工作量确认并不可抵赖等需求场景,然后根据场景建模数字化成响应的智能合约,就创建了不同场景的应用,解决了问题,提供人们服务。

我觉得个人可以尝试的就是场景创新,虽然这个门框比较低,但是抓住历史机会也是会成功的,因为过了一段时间再看,虽然技术门槛是低,但是进入时间恰当的话,经过时间积累,会形成其他壁垒,如用户习惯,服务质量,大众效应。

 

部署使用过程参考https://my.oschina.net/stevex/blog/746669

Scrapy安装

windows10  安装scrapy, windows 下的scrapy 目前暂时不支持python3,因为scrapy 依赖的 Twisted  暂不支持python3,所以只能用python2,并且是win32版本。

目前已支持Windows X64版本 20160928 更新

安装

安装scrapy 前需要如下环境内容:

python2-7-12(win32):

https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi

lxml: https://pypi.python.org/packages/ce/23/e734f2f1a4e3efb40ec60a2cfa6daa08e5d46240c256f9fb146a5b64a9c0/lxml-3.3.5.win32-py2.7.exe#md5=2c10ce9cab81e0155a019fb6c0c3e2e9

libxml2:

http://xmlsoft.org/sources/win32/python/libxml2-python-2.7.7.win32-py2.7.exe

VCForPython27.msi

https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi

安装上诉之后,整个环境已经准备妥当,直接用如下pip 即可将Scrapy 安装好了

[bath]py -2 -m pip install Scrapy[/bath]

python3.5 Scrapy1.1.3安装 20160928

需要使用wheel格式的文件直接本地安装lxml ,Twisted. 这个几个包可恶意从http://www.lfd.uci.edu/~gohlke/pythonlibs/  找到。

lxml:http://www.lfd.uci.edu/~gohlke/pythonlibs/dp2ng7en/lxml-3.6.4-cp35-cp35m-win_amd64.whl

Twisted:http://www.lfd.uci.edu/~gohlke/pythonlibs/dp2ng7en/Twisted-16.4.1-cp35-cp35m-win_amd64.whl

scrapy:https://pypi.python.org/packages/1f/91/81b32afce9676a0542ee42e8755ff1d61a80acd0101035929d7355b8cc50/Scrapy-1.1.3-py2.py3-none-any.whl#md5=eb35996066a3802dd9d2b2070098bdbb

依次安装上述下载的wheel 文件:

[bath]py -3 -m pip install lxml-3.6.4-cp35-cp35m-win_amd64.whl

py -3 -m pip install Twisted-16.4.1-cp35-cp35m-win_amd64.whl

py -3 -m pip install Scrapy-1.1.3-py2.py3-none-any.whl[/bath]

 

运行调试

创建项目

scrapy startproject tutorial

编写spider

运行

scrapy crawl spider_name

scrapy crawl dmoz

在pycharm 环境中,则通过配置 run configuration实现,

%_H8K{A)339[P2A67%V7J}P

 

配置完成后,直接run 就行了,可断点调试

reading—《高绩效教练》

Coach,在足球场上,为什么很多非科班的人也能教导好一个球队,比如狂人穆里尼奥。

前文的例子不能证明说科班出身的教练不行,但是可以得到教练不一定需要非常在行,因为很多教练虽然科班出身,但是他们在球员时代也并非顶级的存在。

很多时候我们会碰到这样的问题,当有人来跟我们针对某事寻求帮助的时候,这时候你职责就是教练。但是日常经验告诉我们,不管我们对该事情给出何种建议评判,对方都很难满意,有时候他们还会跟你顶牛。

WHY?

因为当你给出具体建议的时候,解决这个事情的责任已经转移到我们头上了,但事实上,球场上去踢球进球的还是球员。所以很多时候,当别人来寻求我们帮助的时候,绝大部分其实他们内心深处是有答案的,所以当我们处在教练身份,我们只需要引导对方把这个深藏心底的答案引导出来,让对方自己承担起这个责任。那么如何做么?

HOW?

1.通过提问让对方自己明确目标

2.通过提问让对方认清现状

3.通过提问让对方分解操作步骤

最后,再通过提问让对方确保会执行这些步骤。

最重要的是, 保留自己的意见,因为那是狗屁。

不要评判,不要建议,不要介入。让对方自己承担起责任。因为要实现目标的是对方不是你。你要做的就是理清思路。不要告诉对方要做什么,不要命令,只需要激发对方就好了。因为这也是更加有尊严,更加能自我实现的一种方式。

所以当别人问你问题的时候,你的回答只需要是:

你觉得呢?

如何架构一个新的综合金融交易系统

 

技术产品需求

客户端网站系统(app),业务系统(接口),运维平台

网站系统:

基础系统:

1.用户(帐户)管理系统 2.商品(行情)管理系统 3.订单(交易管理)系统 4.支付系统5.风控系统

增值系统:

客户服务系统,筛选筛选系统,资讯系统。。。

业务系统:

管理系统:

用户管理系统

运营支撑系统

核心系统:

订单交易系统

查询系统

行情系统

增值系统:

数据统计(报表)系统

客户服务系统

 

技术栈选型

1.前端系统

2.后端系统

2.1 负载均衡及http 服务器接入:nginx

2.2 web 应用容器 SOA 服务 Tomcat + dubbo

2.3 文件服务器

        2.3.1 储存方式
        2.3.2 储存容量
        2.3.3 安全性与存取权限控管
        2.3.4 存取效能

2.4 缓存服务器
         2.4.1 分布式Redis缓存
         2.4.2 Memcache缓存

2.5 消息系统
         2.5.1 ActiveMQ
         2.5.2 分布式消息系统Kafka、Rocketmq等

2.6 数据持久层
         2.6.1 关系型数据库
              (1). Mysql

        2.6.2 Nosql
              (1). MongoDB

mysql优化系列(一)

使用新数据库,玩一段时间后,我想大家就应该会碰到一系列的小问题,那是正常的,因为就像处女朋友一样,作为一个负责的男人,不能随便玩一玩了事。

当然,本人也不是泡妞高手,所以也需要不断学习充电,当然老毛子说理论实践是要结合的,在此留下一记。

    1.全表扫描

查询一定要避免全表扫描,如果你有前任,不管她的名字是不是叫oracle,你一定吃过全表扫描的亏,如果很不幸,你一直是只单身狗,那么你也不要沮丧,这里有现成的理论,单身狗们快拿去实践一下:

  • 在查询条件字段建立索引,这是最基本的常识,如果你不记牢你女朋友的电话号码,你大冬天的每次都去她楼下找她么!当然索引也不是越多越好,就像衣服穿多了,你何时才能上三垒!insert update 看到索引就说不要不要的!
  • 在查询条件中,不要拿null值进行判断,既然这样,如果可以,请把你的字段都设置成非NULL,跟默认值进行判断,0 就是0,NULL是什么鬼,你女朋友一定会河东狮吼!
  • 对于 like 这类关键字,大家也尽量少用为好,不要问我为什么,你女朋友真的要大海捞针!
  • 不要给你女朋友太多的选择条件,直接告诉她怎么做,所以 or 这种条件字段也尽量不要用了!
  • 如果字段可以使用 int 类型,那么就不要使用 字符串类型,你女朋友的脑子有时候没有你想象中的那么好,你把字符串给她一个个对比,你们约好的出门时间应该又要推迟了,电影也只能看后半场了,所以给她处理的东西也越简单越好.

当然,mysql 既然是你的新女朋友,那么她也会有自己的一些特性,请在查询的时候限制她查询的范围,limit n,你只需要 n个记录,那么就不要让她找出 n+m来,不然她真的会这么干!

有时候,即使你给了限制,还是会出错!

请看

select * from order where kj_customer_acco =

@kj_customer_acco and position_int > @position_int order by position_int asc limit 0,@request_num

上面给出的示范,除了

select *

这个是不好的外(增加多余的网络传输压力等),其他应该都是几乎完美的一个语句,但是就是如此,有时候你女朋友还是爽约了,那一天你在雨中苦等了2小时,以为会有一场雨中浪漫的约会,结果是你淋成了落汤鸡!因为你没有从实际国情出发,我们是一国两制的社会,胡乱套用也会水土不服,所以我们一定要具体问题具体分析,那么就先来看下国情:

CREATE TABLE order
(
	position_int                   bigint          NOT NULL AUTO_INCREMENT,
	kj_customer_acco               varchar(10)     DEFAULT ' '        ,
	update_date                    int             DEFAULT 0          ,
	update_time                    int             DEFAULT 0          ,
	PRIMARY KEY(position_int)
);
CREATE INDEX idx_position_int ON order(position_int ASC );

然后我们造了测试数据进去

begin
    declare i int default 1000;
    
	while i < 1300 do
    BEGIN
    declare j int default 1;
		while j < 9060 do
       insert into `order` values(DEFAULT,i,20151203,111111);
       set j=j+1;
    end while; 
    set i=i+1;
    END;
   end while;
   commit;
end

我们使用上面的语句对这个表进行翻页式查询,在查询中,每当如下语句

select * from order where kj_customer_acco = @kj_customer_acco  and position_int > @position_int

查询出来的数据不足 @request_num,的时候,就会特别的慢,使用 EXPLAIN 关键字查看下执行计划

image

我们发现查询搜索的边界在我们的意料之外,它的搜索范围是1231780行数据,当剩余查询的数据条数大于@request_num,因为我们加了limit 的限制,所以查询搜索到@request_num 条数据的时候就结束搜索了,但是当剩余查询的有效数据量不足@request_num时,就会继续往下查询把rows 条记录都会搜一遍!