参考文献
什么是区块链
https://blog.csdn.net/HUIBUR/article/details/137952996
国产区块链webase平台
https://fisco-bcos-documentation.readthedocs. tyio/zh-cn/latest/docs/introduction.html
https://blog.csdn.net/gitblog_00018/article/details/138061832
1.环境设置
1.1. 本地环境
springboot本地部署:
操纵系统:Windows 11 x64
处理惩罚器:11th Gen Intel® Core™ i5-11300H @ 3.10GHz 3.11 GHz
区块链本地部署:
操纵系统:ubuntu 20
处理惩罚器:11th Gen Intel® Core™ i5-11300H @ 3.10GHz 3.11 GHz
项目环境设置:
jdk 19
apache maven 3.9.3
apache tomcat 9.0.7
mysql 5.7.26
navicat 16
node 16.17.1
npm 8.15.0
1.2.阿里云环境
2.区块链
2.1 前言
~~~~~~ 在当今数字化时代,区块链技能已经成为环球范围内备受瞩目的话题。从金融到供应链,从物联网到数字身份,区块链正在以惊人的速度渗出到各个行业,并在重塑着我们的社会和经济格局。
~~~~~~ 区块链最初因其作为比特币背后技能的而引起人们的关注。但现在,它已经远远超出了仅仅作为数字货币的用途。它被认为是一种革命性的技能,有潜力改变我们传统的商业模式、加强数据安全和可信度,并促进更加公平和透明的生意业务。
~~~~~~ 区块链的核心头脑是建立一个去中心化、不可篡改的分布式账本,使得数据的传输和存储变得更加安全、高效和可靠。在这个账本上,全部的生意业务都被记录下来,并通过加密技能保护,使得数据不易被篡改或伪造。这种去中心化的特性意味着不再需要依赖于单一的中心化机构或权势巨子来验证和管理数据,而是由网络中的参与者共同维护。
~~~~~~ 正是由于这些特性,区块链技能正在引发各个行业的厘革。在金融领域,它正在改变支付和结算方式,进步资产生意业务的效率和安全性;在供应链领域,它正在进步物流信息的透明度和可追溯性;在数字身份领域,它正在帮助解决身份验证和个人隐私保护的题目。
~~~~~~ 然而,尽管区块链技能充满了潜力,但也面临着一些挑战,如可扩展性、性能题目、法律法规等。因此,我们需要深入相识区块链技能,探索其优势和局限性,并不停创新和美满,以实现
2.2 什么是区块链
区块链是一种分布式数据库技能,它以块的情势存储数据,并使用密码学方法保证数据的安全性和完备性。每个块包含一定数量的生意业务信息,并通过加密链接到前一个块,形成一个不停增长的链条。这种设计使得数据在网络中无法被篡改,因为任何实验修改一个块的数据都会粉碎整个链的一连性。通已往中心化的网络布局,区块链技能实现了对数据的分布式共享和管理,从而在不需要信托中介的环境下确保了数据的安全和可靠性。
2.2.1 区块(Block):
区块是区块链中的根本单位,用于存储数据。每个区块包含了一定数量的生意业务信息,如数字货币的转账记录、智能合约的执行结果等。区块还包含一个称为区块头的元数据,其中包罗了对上一个区块的引用、时间戳、随机数以及用于验证区块内容的哈希值等信息。
2.2.2 链(Chain):
区块链是由一系列按照特定顺序毗连而成的区块构成的链条。每个区块中都包含了指向前一个区块的哈希值,形成了一个不可篡改的数据链。这种一连的链接保证了区块链中的数据不可逆地被记录和生存。
2.2.3 分布式账本(Distributed Ledger):
区块链是一种分布式账本,数据的存储和管理分布在网络中的多个节点上,而不是集中存储在单一的中心化服务器上。每个节点都包含了完备的账本副本,并通过共识机制来保持账本的同等性。这种分布式的特性使得区块链更加安全和可信。
2.2.4 去中心化(Decentralization):
区块链的去中心化特性意味着不存在单一的管理者或控制者,全部的参与者共同维护和管理网络。数据的验证和生意业务的确认是通过网络中的节点之间的协作和共识告竣的,而不是依赖于单一的中心化机构。去中心化使得区块链网络更加民主、透明和公平。
总的来说,区块链的根本概念包罗区块、链、分布式账本和去中心化等重要部分,这些概念共同构成了区块链技能的核心特性和工作原理。
2.3 技能原理
区块链技能的原理涉及到数据布局、加密技能和共识机制等多个方面:
2.3.1 区块链的数据布局:
区块链接纳链式数据布局,由一系列按照特定顺序毗连的区块构成。每个区块包含了一定数量的生意业务数据和区块头信息。区块头包罗了前一个区块的哈希值、时间戳、随机数以及用于验证区块内容的哈希值等信息。区块链中的每个区块都通过其前一个区块的哈希值链接在一起,形成了一个不可篡改的数据链。
2.3.2加密技能:
区块链使用了多种加密技能来保护数据的安全性和隐私性。其中最重要的是哈希函数和公钥加密。
哈希函数用于将任意长度的数据转换为固定长度的哈希值。在区块链中,每个区块都包含了前一个区块的哈希值,通过哈希值链的方式保证了数据的完备性和一连性。
公钥加密技能用于实现数字署名和加密通讯。数字署名用于验证生意业务的发送者身份和生意业务的完备性,确保生意业务不被篡改。加密通讯则用于保护数据在网络中的传输过程中的安全性。
2.3.3、共识机制:
区块链通过共识机制来确保网络中的节点告竣同等,从而保持数据的同等性和完备性。常见的共识机制包罗工作量证明(PoW)、权益证明(PoS)、权益抵押(DPoS)等。
工作量证明(PoW)是比特币和许多其他区块链项目中最常见的共识机制,它要求节点通过解决一定的数学难题来证明其对网络的贡献,从而获得天生新区块的权利。权益证明(PoS)则是另一种常见的共识机制,它根据节点持有的加密货币数量来决定其对网络的投票权。
总的来说,区块链的技能原理涉及到链式数据布局、加密技能和共识机制等多个方面,这些技能共同构成了区块链技能的核心特性和工作原理。
2.4 架构模子
一般说来,区块链系统由数据层、网络层、共识层、鼓励层、合约层和应用层构成。
在这里插入图片形貌
2.4.1 数据层
封装了底层数据区块以及相关的数据加密和时间戳等基础数据和根本算法。
2.4.2网络层
则包罗分布式组网机制、数据传播机制和数据验证机制等;共识层主要封装网络节点的各类共识算法。
2.4.3 鼓励层
将经济因素集成到区块链技能体系中来,主要包罗经济鼓励的发行机制和分配机制等。
2.4.4 合约层
主要封装各类脚本、算法和智能合约,是区块链可编程特性的基础。
2.4.5 应用层
则封装了区块链的各种应用场景和案例。该模子中,基于时间戳的链式区块布局、分布式节点的共识机制、基于共识算力的经济鼓励和灵活可编程的智能合约是区块链技能最具代表性的创新点。
2.5 区块链为什么能够取代数据库
2.5.1. 去中心化
传统数据库: 传统数据库通常是集中式的,依赖于一个或多个中心服务器举行数据存储和管理。全部的数据哀求和操纵都通过中心服务器举行,这使得系统存在单点故障风险。一旦中心服务器出现题目,整个系统就大概瘫痪。
区块链: 区块链是一种分布式账本技能,每个参与节点都有一个完备的数据库副本。这种去中心化的设计消除了单点故障的风险,即使某个节点失效,系统仍旧可以正常运行。这进步了系统的鲁棒性和可靠性,特别是在需要高可用性的场景中。
2.5.2. 不可篡改性
传统数据库: 在传统数据库中,数据可以被随意修改和删除,尽管可以通过日记和权限控制来防止篡改,但仍旧无法完全避免内部或外部的恶意举动。
区块链: 区块链通过密码学技能和共识机制确保数据一旦写入就无法篡改。每个区块都包含前一个区块的哈希值,形成一个链条布局,这使得任何篡改举动都会被立即发现。区块链的这种不可篡改性特别适用于需要高度数据完备性的场景,如金融生意业务和医疗记录。
2.5.3. 透明性和可追溯性
传统数据库: 传统数据库的访问权限通常是受限的,数据的透明性较低,需要信托管理员的诚实和系统的完备性。数据的追溯性也需要依赖复杂的日记记录和审计机制。
区块链: 区块链上的全部生意业务都是公开透明的,任何人都可以检察全部历史记录。这种透明性大大淘汰了信息不对称,进步了系统的信托度。同时,区块链的链式布局使得全部数据都具有可追溯性,任何数据的来源和变动都可以被清晰地追踪到。这在供应链管理、食品安全等需要严酷追溯的领域具有重要意义。
2.5.4. 去信托化
传统数据库: 传统数据库的操纵依赖于中心机构或第三方的信托,这对于多方参与、彼此不完全信托的环境中是一个难点。
区块链: 区块链通过共识机制(如PoW、PoS等)来确保数据的真实性和同等性,无需依赖中心机构或第三方。每个参与节点都参与数据的验证和记录,确保了数据的公正性和可靠性。这种去信托化的特点非常适用于多方协作、需要高信托度的场景,如跨境支付和团结审计。
2.5.5. 安全性
传统数据库: 传统数据库可以通过加密技能保护数据,但仍旧存在被攻破的风险,尤其是当数据库被集中存储时,一旦被攻破,全部数据都大概泄漏。
区块链: 区块链通过高级加密技能和分布式存储增强了数据的安全性。数据在传输和存储过程中都经过加密,且分布在多个节点上,攻击者难以同时攻破全部节点。即使某个节点被攻破,其他节点的数据仍旧是安全的。
2.5.6. 智能合约
传统数据库: 在传统数据库中,自动化流程需要复杂的编程和外部系统集成,实现难度高且维护成本大。
区块链: 区块链支持智能合约,这是运行在区块链上的自动执行代码,当满足预设条件时自动触发。智能合约可以实现自动化的生意业务和流程,淘汰人工干预,进步效率和正确性。智能合约特别适用于需要自动化执行和严酷规则遵循的场景,如保险理赔和供应链自动化。
2.5.7. 数据同等性
传统数据库: 在分布式数据库系统中,数据同等性题目是一个复杂的挑战,需要借助分布式同等性协议(如Paxos、Raft等)来解决,且实现和维护难度较高。
区块链: 区块链通过共识算法(如PoW、PoS等)确保全部节点的数据同等性和同步性。每个节点都参与共识过程,保证了整个系统数据的同等性和完备性。这种机制使得区块链在多方协作、需要高度同等性的场景中更具优势。
2.6 区块链平台FISCO BCOS
区块链技能的应用:研究怎样使用区块链技能实现投票数据的安全存储和不可篡改性。将投票信息以区块的情势存储在区块链上,确保数据的安全性和可靠性。研究怎样使用区块链的去中心化特性防止数据被篡改或删除。同时,研究怎样使用区块链的透明性和可追溯性验证投票数据的真实性和完备性,增加投票过程的公正性和可信度。
2.6.1 区块链平台
~~~~~~~ 区块链是一种分布式数据库,由多个节点共同维护,每个节点生存着完备的数据库副本。本系统为了保证投票的公平性,投票数据的安全性,可追溯性,不可篡改性,使用开源的FISCO BCOS区块链平台。
~~~~~~~ FISCO BCOS是一个面向同盟链的区块链平台,FISCO BCOS接纳基于账本的多链架构,FISCO BCOS还支持同盟链模式,允许多个构造共同参与链的管理和运维。FISCO BCOS支持多种共识算法,使用Solidity语言编写智能合约,智能合约在链上执行,实现业务逻辑的自动化和可信执行。智能合约可以定义数据布局、业务规则和生意业务操纵,通过调用合约的函数来举行数据的读写和业务逻辑的执行。
~~~~~~~ FISCO BCOS提供了隐私保护机制,包罗数据加密、合约隐私、生意业务隐私等。通过使用零知识证明、同态加密等技能,可以保护链上数据和生意业务的隐私性,确保敏感信息不被泄漏。
~~~~~~~ FISCO BCOS链保证数据存储在链上的每个节点上,而不是集中存储在单一的中心折务器上。这种去中心化的存储方式确保了数据的可靠性和安全性,防止数据的单点故障和篡改。每个数据生意业务都会被记录在一个区块中,并通过共识算法告竣同等。一旦数据被写入区块链,就无法被修改或删除,保证了数据的不可篡改性。对于投票数据在链上进一步加密,数据安全性更高,由于每个数据生意业务都被记录在区块链上,因此可以实现数据的完全追溯。任何人都可以检察和验证已往的生意业务记录,从而建立信托和透明度。这对投票场景非常有效。
2.6.2 区块链模块设计
系统使用开源的FISCO BCOS区块链平台保证投票数据的安全性,可追溯性,不可篡改性。区块链部署的linux虚拟机上,使用虚拟机的ip地址举行与区块链举行交互。浏览器使用HTTP协议向虚拟机IP地址发送哀求。哀求经过本地网络,到达虚拟机所在的物理呆板。物理呆板根据哀求的IP地址和端口号找到对应的虚拟机实例。哀求被发送给虚拟机内的区块链服务器。服务器处理惩罚哀求,天生HTTP响应。响应经过虚拟机内部网络,返回给物理呆板。物理呆板收到响应后,将其发送回浏览器。图1展示该过程架构图。
图1 区块链架构图
FISCO BCOS链使用Solidity语言编写智能合约,智能合约在链上执行。智能合约数据储存布局为串类型,通过调用合约的函数来举行数据的储存和查询的功能。由于性能题目,在linux虚拟机部署三个节点举行数据备份,保障链的完备性、安全性和可靠性。
2.7 区块链可视化平台webase
2.7.1 项目简介
是微众银行(WeBank)金融科技团队开辟的一个开源项目,它是一个基于区块链的前端访问控制与管理平台,旨在为区块链应用提供安全、高效、易用的底层服务。WeBASE 提供了包罗节点管理和监控、用户管理、合约管理等功能,支持同盟链场景下的多种主流区块链框架,如 Fabric 和 FISCO BCOS。
2.7.2技能分析
多链兼容:WeBASE 支持对接多种区块链平台,如 Hyperledger Fabric 和微众银行的 FISCO BCOS,这使得它能够灵活适应差别场景和需求。
安全性:提供证书管理,确保用户访问区块链的安全性;同时具备节点监控功能,可以实时监测并预警区块链网络中的异常环境。
易用性:通过 Web 界面提供友爱的操纵体验,无需深入相识区块链底层技能,即可举行节点管理、智能合约部署及调用等操纵。
可扩展性:WeBASE 设计了模块化架构,方便添加新的功能或适配更多的区块链系统。
API 接口:提供了丰富的 API 接口,方便开辟者集成到自己的业务系统中。
2.7.3 应用场景
企业级区块链应用:在金融、供应链、物联网等领域,企业可以使用 WeBASE 快速搭建对区块链网络的管理和访问。
研发与测试:开辟职员可以在开辟和测试环境中使用 WeBASE 举行区块链节点管理,进步效率。
教诲与学习:对于学习区块链技能的人来说,WeBASE 是一个很好的实践工具,它可以简化操纵,让初学者更专注于明白区块链的核心概念。
2.7.4 特点总结
多链支持:适应多种区块链框架。
安全可靠:内置证书管理,实时节点监控。
界面友爱:Web 管理界面,低落使用门槛。
易于集成:丰富的 API 接口,便于业务系统集成。
模块化设计:易于扩展,满足未来需求。
2.8 区块链的实现
2.8.1平台搭建
在VMware软件上安装linux虚拟机,在虚拟机上先安装FISCO BCOS链所需有的全部前提环境,如mysql5.7、python3.8、jdk1.8等。使用FISCO BCOS官方文档一键部署webase平台。先下载所需安装包并更改common.properties文件相关设置,运行python3 deploy.py installAll命令成功安装,python3 deploy.py installAll一键启动,如图2所示。
图2 FISCO BCOS链启动图
Linux虚拟机上启动成功后,访问http://192.168.198.132:5000/#/home地址计入管理平台,如图3所示。
图3 FISCO BCOS管理平台图
FISCO BCOS管理平台,即WeBASE管理平台,是由四个WeBASE子系统构成的一套管理FISCO-BCOS同盟链的工具集。部署架构如图4所示。
图4 WeBASE四个服务的部署架构图
2.8.2 智能合约的编写
FISCO BCOS区块链向外部提供了接口,可以通过FISCO BCOS提供的SDK来调用这些接口。本系统基于Python SDK与区块链交互数据,具体可以安装FISCO BCOS官方文档举行部署。由于系统是将共识的数据上传到区块链上,使用区块链特性使得投票系统更加安全和公平。需要创建私钥用户和智能合约,私钥用户可以通过命令python console2.py newaccoun创建需要手动生存私钥,将智能合约通过私钥用户部署到链上。智能合约部署如图5所示。
图5 合约部署图
在合约部署成功后,可以在合约IDE页面的右上角点击发生意业务,向合约发送生意业务举行合约调用。合约调用如图6所示,其中,图6-1表示调用合约中的addCandidate方法来添加数据,图6-2表示调用合约中的getCandidateInfo方法来根据主键查询完备信息。
图6-1 合约调用图1
图6-2 合约调用图2
2.8.3 检察生意业务回执
生意业务发送成功后,将返回生意业务回执。可以在数据概览-生意业务列表-更多中根据transactionHash搜索生意业务,通过生意业务解析和Event解析检察可视化的生意业务回执信息。生意业务回执如图7所示。
图7-1 生意业务回执图1
图7-2 生意业务回执图2
3.数据库
3.1数据库的根本原理
3.1.1.什么是数据库
~~~~~~ 你正在读本 SQL 教程,这表明你需要以某种方式与数据库打交道。SQL 正是用来实现这一任务的语言,因此在学习 SQL 之前,你应该对数据库及数据库技能的某些根本概念有所相识。
~~~~~~ 你大概还没故意识到,实在自己一直在使用数据库。每当你在手机上选取接洽人,或从电子邮件地址簿里查找名字时,就是在使用数据库。你在网站上举行搜索,也是在使用数据库。你在工作中登录网络,也需要依赖数据库验证用户名和密码。即使是在自动取款机上使用 ATM 卡,也要使用数据库举行密码验证和余额查询。
~~~~~~ 虽然我们一直都在使用数据库,但对究竟什么是数据库并不十分清晰。更何况人们大概会使用同一个数据库术语表示差别的事物,进一步加剧了这种混乱。因此,我们起首给出一些最重要的数据库术语,并加以说明。
3.1.2 数据库
~~~~~~ 每个人家里都会有冰箱,冰箱是用来干什么的?冰箱是用来存放食物的地方。
~~~~~~ 同样的,数据库是存放数据的地方。正是因为有了数据库后,我们可以直接查找数据。例如你每天使用余额宝检察自己的账户收益,就是从数据库读取数据后给你的。
数据库(database)
生存有构造的数据的容器(通常是一个文件或一组文件)。
注意:误用导致肴杂
人们通常用数据库这个术语来代表他们使用的数据库软件,这是不正确的,也因此产生了许多肴杂。确切地说,数据库软件应称为数据库管理系统(DBMS)。数据库是通过 DBMS 创建和操纵的容器,而具体它究竟是什么,情势怎样,各种数据库都不一样。
3.1.3表
~~~~~~ 你往文件柜里放资料时,并不是随便将它们扔进某个抽屉就完事了的,而是在文件柜中创建文件,然后将相关的资料放入特定的文件中。
~~~~~~ 在数据库领域中,这种文件称为表。表是一种布局化的文件,可用来存储某种特定类型的数据。表可以生存顾客清单、产物目次,或者其他信息清单。
表(table)
~~~~~~ 某种特定类型数据的布局化清单。
~~~~~~ 这里的关键一点在于,存储在表中的数据是同一种类型的数据或清单。决不应该将顾客的清单与订单的清单存储在同一个数据库表中,否则以后的检索和访问会很困难。应该创建两个表,每个清单一个表。
~~~~~~ 数据库中的每个表都有一个名字来标识自己。这个名字是唯一的,即数据库中没有其他表具有相同的名字。
说明:表名
~~~~~~ 使表名成为唯一的,实际上是数据库名和表名等的组合。有的数据库还使用数据库拥有者的名字作为唯一名的一部分。也就是说,虽然在一个数据库中不能两次使用相同的表名,但在差别的数据库中完全可以使用相同的表名。
~~~~~~ 表具有一些特性,这些特性定义了数据在表中怎样存储,包罗存储什么样的数据,数据怎样分解,各部分信息怎样命名等信息。形貌表的这组信息就是所谓的模式(schema),模式可以用来形貌数据库中特定的表,也可以用来形貌整个数据库(和其中表的关系)。
模式
关于数据库和表的布局及特性的信息。
3.1.4列和数据类型
表由列构成。列存储表中某部分的信息。
列(column)
~~~~~~ 表中的一个字段。全部表都是由一个或多个列构成的。
~~~~~~ 明白列的最好办法是将数据库表想象为一个网格,就像个电子表格那样。网格中每一列存储着某种特定的信息。例如,在顾客表中,一列存储顾客编号,另一列存储顾客姓名,而地址、城市、州以及邮政编码全都存储在各自的列中。
提示:数据分解
~~~~~~ 正确地将数据分解为多个列极为重要。例如,城市、州、邮政编码应该总是彼此独立的列。通过分解这些数据,才有大概使用特定的列对数据举行分类和过滤(如找出特定州或特定城市的全部顾客)。如果城市和州组合在一个列中,则按州举行分类或过滤就会很困难。
~~~~~~ 你可以根据自己的具体需求来决定把数据分解到何种程度。例如,一般可以把门牌号和街道名一起存储在地址里。这没有题目,除非你哪天想用街道名来排序,这时,最好将门牌号和街道名分开。
~~~~~~ 数据库中每个列都有相应的数据类型。数据类型(datatype)定义了列可以存储哪些数据种类。例如,如果列中存储的是数字(或许是订单中的物品数),则相应的数据类型应该为数值类型。如果列中存储的是日期、文本、解释、金额等,则应该规定好恰当的数据类型。
数据类型
~~~~~~ 允许什么类型的数据。每个表列都有相应的数据类型,它限定(或允许)该列中存储的数据。
~~~~~~ 数据类型限定了可存储在列中的数据种类(例如,防止在数值字段中录入字符值)。数据类型还帮助正确地分类数据,并在优化磁盘使用方面起重要的作用。因此,在创建表时必须特别关注所用的数据类型。
注意:数据类型兼容
数据类型及其名称是 SQL 不兼容的一个主要原因。虽然大多数根本数据类型得到了同等的支持,但许多高级的数据类型却没有。更糟的是,偶然会有相同的数据类型在差别的 DBMS 中具有差别的名称。对此用户毫无办法,重要的是在创建表布局时要记住这些差别。
3.1.5 行
表中的数据是按行存储的,所生存的每个记录存储在自己的行内。如果将表想象为网格,网格中垂直的列为表列,程度举动表行。
例如,顾客表可以每行存储一个顾客。表中的行编号为记录的编号。
行(row)
表中的一个记录。
说明:是记录照旧行?
你大概听到用户在提到行时称其为数据库记录(record)。这两个术语多半是可以互通的,但从技能上说,行才是正确的术语。
3.1.6 主键
表中每一行都应该有一列(或几列)可以唯一标识自己。顾客表可以使用顾客编号,而订单表可以使用订单 ID。雇员表可以使用雇员 ID。书目表则可以使用国际标准书号 ISBN。
主键(primary key)
一列(或几列),其值能够唯一标识表中每一行。
唯一标识表中每行的这个列(或这几列)称为主键。主键用来表示一个特定的行。没有主键,更新或删除表中特定行就极为困难,因为你不能保证操纵只涉及相关的行,没有伤及无辜。
提示:应该总是定义主键
虽然并不总是需要主键,但多数数据库设计者都会保证他们创建的每个表具有一个主键,以便于以后的数据操纵和管理。
表中的任何列都可以作为主键,只要它满足以下条件:
任意两行都不具有相同的主键值;
每一行都必须具有一个主键值(主键列不允许空值 NULL);
主键列中的值不允许修改或更新;
主键值不能重用(如果某行从表中删除,它的主键不能赋给以后的新行)。
主键通常定义在表的一列上,但并不是必须这么做,也可以一起使用多个列作为主键。在使用多列作为主键时,上述条件必须应用到全部列,全部列值的组合必须是唯一的(但其中单个列的值可以不唯一)。
3.2 数据库的种类
数据库共有2种类型:关系型数据库、非关系型数据库 。
3.2.1、关系数据库
MySQL、
MariaDB(MySQL的取代品)、
Percona Server(MySQL的取代品·)、
PostgreSQL、
Microsoft Access、
Google Fusion Tables、
SQLite、
DB2、
FileMaker、
Oracle、
SQL Server、
INFORMIX、
Sybase、
dBASE、
Clipper、
FoxPro、
foshub。
几乎全部的数据库管理系统都配备了一个开放式数据库毗连(ODBC)驱动程序,令各个数据库之间得以互相集成。
3.2.2、非关系型数据库(NoSQL)
redis、
MongoDB、
Memcache、
HBase、
BigTable、
Cassandra、
CouchDB、
Neo4J。
3.3 关系型数据库和非关系型数据库的区别
3.3.1关系型数据库
关系型数据库最典型的数据布局是表,由二维表及其之间的接洽所构成的一个数据构造
长处:
1、易于维护:都是使用表布局,格式同等;
2、使用方便:SQL语言通用,可用于复杂查询;
3、复杂操纵:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:
1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表布局,灵活度稍欠;
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。
3.3.2 非关系型数据库
非关系型数据库严酷上不是一种数据库,应该是一种数据布局化存储方法的集合,可以是文档或者键值对等。
长处:
1、格式灵活:存储数据的格式可以是key,value情势、文档情势、图片情势等等,文档情势、图片情势等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
3、高扩展性;
4、成本低:nosql数据库部署简单,根本都是开源软件。
缺点:
1、不提供sql支持,学习和使用成本较高;
2、无事件处理惩罚;
3、数据布局相对复杂,复杂查询方面稍欠。
3.3.3 部分数据库的区别:
redis: (非关系型数据库----键值数据库)
MongoDB:(非关系型数据库----文档数据库)
HBase:(非关系型数据库----列存储数据库)
Neo4J : (非关系型数据库----图形数据库)
补充:
数据库模子:
对象模子、
层次模子(轻量级数据访问协议)、
网状模子(大型数据储存)、
关系模子、
面向对象模子、
半布局化模子、
平面模子(表格模子,一般在情势上是一个二维数组。如表格模子数据Excel)。
3.4mysql数据库
3.4.1. mysql的根本概念
数据库(database)就是一个存储数据库的仓库,为了方便数据的存储和管理,它将数据按照特定的规律存储在磁盘上。通过数据库管理系统,可以有效的构造和管理存储在数据库中的数据。mysql数据库就是如许一个关系型数据库管理系统(RDBMS),它可以称得上是现在运行速度最快的SQL数据库管理系统。
3.4.1.1 mysql的优势
mysql是一款自由软件,任何人可以从官网网址中下载。mysql是一个真正的多用户,多线程sql数据库服务器。它是以客户/服务器布局的实现,由一个服务程序mysqld和许多差别的客户程序和库构成。它能够快捷、有效和安全地处理惩罚大量的数据。相对于oracle等数据库来说,mysql在使用时非常简单。mysql的主要目的是快捷、便捷和易用
以下是mysql的一些特点:
1、开源和免费:
MySQL是开源的,而且可以免费使用。这使得MySQL成为开辟职员和小型企业的首选数据库。
2、可扩展性:
MySQL可以轻松地扩展以支持更大的数据集和更高的并发用户。MySQL提供了许多扩展和插件,以帮助用户轻松地举行扩展。
3、跨平台支持:
MySQL可以在多个平台上运行,包罗Windows、Linux、Unix、macOS等。
4、安全性:
MySQL具有强大的安全功能,可以保护数据免受未经授权的访问。MySQL提供了许多安全功能,例如加密、用户访问控制和审计等。
5、高可用性:
MySQL支持主从复制和自动故障转移,这使得MySQL可以实现高可用性和灾备恢复。
6、性能:
MySQL具有杰出的性能,可以轻松地处理惩罚大型数据集和高并发用户。MySQL支持索引、查询优化和缓存等功能,以进步性能。
7、支持大型企业应用程序:
MySQL可以处理惩罚大型企业级应用程序和高流量网站。许多大型企业和网站使用MySQL作为他们的数据库管理系统。
3.4.1.2 mysql的发展历史
MySQL是由瑞典公司MySQL AB开辟的一种关系型数据库管理系统。其名字的由来是由MySQL AB的首创人之一Michael Widenius取的,最初取名为“My”(他的女儿的名字),加上“SQL”(布局化查询语言)的缩写构成。因此,MySQL这个名字代表着“我的SQL”,夸大MySQL作为一个开源软件,可以根据用户的需求举行个性化的定制和修改。MySQL的名字既简单又易于记忆,因此在数据库市场上得到了广泛的认可和应用。
3.4.2. mysql的特性
mysql是一个真正的多用户、多线程sql数据库服务器。SQL是世界上最流行的和标准化的数据库语言。其特性如下:
使用C和C++语言编写,并使用了多种编译器举行测试,保证了源代码的可移植性。
支持多种操纵系统,如Linux、Mac os、Windows等。
为多种编程语言提供了API。这些编程语言包罗C、C++、Java、Perl、 PHP、Ruby、Eiffel、Tcl等。
支持多线程,充分使用CPU资源。
优化SQL查询算法,有效进步查询速度。
既能够作为一个单独的应用程序在客户端服务器网络环境中,也能够作为一个库而嵌入到其他软件中提供多语言支持,常见的编码如中文的GB2312、BIG5,日文的Shift_JIS等都可以作为数据数据的表名和数据列名。
提供TCP/IP、ODBC和JDBC等多种数据库毗连途径。
提供用于管理、检查、优化数据库操纵的管理工具。
可以处理惩罚拥有千万条记录的大型数据库。
现在的最新版本是mysql9.0版本。
3.4.2.1 mysql的安装
可以去官网下载
下载完成后可以在终端检察
3.4.2.2 数据库常用对象
在mysql数据库中,表、视图、存储过程和索引等具体存储数据或对数据举行操纵的实体都被称为数据库对象,下面先容几种常用的数据库对象:
1、表:
表是数据库中全部数据的数据库对象,由行和列构成,用于构造和存储数据。
2、字段:
表中的每列称为一个字段,字段具有自己的属性,如字段类型、字段大小等。其中,字段类型是字段中最重要的属性,它决定了字段能够存储那种数据。SQL规范支持5中根本类型的字段类型:字符型、文本型、数值型、逻辑型和日期时间类型。
3、索引:
索引是一个单独的、物理的数据库布局。它是依赖于表建立的,在数据库中索引使数据库程序无需对整个表举行扫描,就可以在其中找到所需要的数据。
4、视图:
视图是从一张表或者多张表中导出的表,是用户检察数据表中数据的一张方式。表中包罗几个被定义的数据列与数据行,其布局和数据建立在对表的查询基础之上。
5、存储过程:
存储过程是一组为了完成特定功能的SQL语句集合(包含查询、插入、删除和更新等操纵),经编译后以名称的情势存储在SQL sever服务器端端数据库中,由用户通过指定存储过程的名字来执行,当这个存储过程被调用执行时,这些操纵也会同时执行。
3.4.3. mysql的存储引擎
MySQL的存储引擎(storage engine)是指用于存储和检索数据的底层软件组件。MySQL支持多种差别的存储引擎,每种引擎都有自己的特点和优势,应该根据具体需求选择合适的引擎。
以下是MySQL常见的存储引擎:
1、InnoDB
InnoDB是MySQL默认的存储引擎,支持ACID事件处理惩罚和行级锁定,适用于高并发的OLTP应用。它还支持外键约束和瓦解恢复等高级特性。
2、MyISAM
MyISAM是MySQL的传统存储引擎,不支持事件和行级锁定,但对于读多写少的应用非常得当。它的特点是速度快,占用资源少,适用于数据仓库和大型数据表。
3、Memory
Memory存储引擎将数据存储在内存中,速度非常快,但缺点是轻易丢失数据,适用于临时数据表和缓存。它还支持HASH和B-tree索引。
4、CSV
CSV存储引擎将数据以CSV格式存储在文件中,适用于存储大量文本数据,但不支持索引和事件处理惩罚。
5、Archive
Archive存储引擎是一种高度压缩的存储引擎,适用于存储历史数据或归档数据,但不支持索引和事件处理惩罚。
6、Blackhole
Blackhole存储引擎不实际存储数据,全部写入操纵都被丢弃,适用于数据复制和数据同步等应用场景。
7、Federated
Federated存储引擎可以将远程服务器上的表映射为本地表,支持跨服务器的查询和数据操纵。
总的来说,选择得当自己应用场景的存储引擎可以进步数据库的性能和可靠性。
3.5mysql操纵语句
3.5.1 数据库
- # 查看所有的数据库
- SHOW DATABASES ;
- # 创建一个数据库
- CREATE DATABASE k;
- # 删除一个数据库
- DROP DATABASE k;
- # 使用这个数据库
- USE k;
复制代码 3.5.2 表
- # 查看所有的表
- SHOW TABLES ;
- # 创建一个表
- CREATE TABLE n(id INT, name VARCHAR(10));
- CREATE TABLE m(id INT, name VARCHAR(10), PRIMARY KEY (id), FOREIGN KEY (id) REFERENCES n(id), UNIQUE (name));
- CREATE TABLE m(id INT, name VARCHAR(10));
- # 直接将查询结果导入或复制到新创建的表
- CREATE TABLE n SELECT * FROM m;
- # 新创建的表与一个存在的表的数据结构类似
- CREATE TABLE m LIKE n;
- # 创建一个临时表
- # 临时表将在你连接MySQL期间存在。当断开连接时,MySQL将自动删除表并释放所用的空间。也可手动删除。
- CREATE TEMPORARY TABLE l(id INT, name VARCHAR(10));
- # 直接将查询结果导入或复制到新创建的临时表
- CREATE TEMPORARY TABLE tt SELECT * FROM n;
- # 删除一个存在表
- DROP TABLE IF EXISTS m;
- # 更改存在表的名称
- ALTER TABLE n RENAME m;
- RENAME TABLE n TO m;
- # 查看表的结构(以下五条语句效果相同)
- DESC n; # 因为简单,所以建议使用
- DESCRIBE n;
- SHOW COLUMNS IN n;
- SHOW COLUMNS FROM n;
- EXPLAIN n;
- # 查看表的创建语句
- SHOW CREATE TABLE n;
复制代码 3.5.3 表的布局
- # 添加字段
- ALTER TABLE n ADD age VARCHAR(2) ;
- # 删除字段
- ALTER TABLE n DROP age;
- # 更改字段属性和属性
- ALTER TABLE n CHANGE age a INT;
- # 只更改字段属性
- ALTER TABLE n MODIFY age VARCHAR(7) ;
复制代码 3.5.4 表的数据
- # 增加数据
- INSERT INTO n VALUES (1, 'tom', '23'), (2, 'john', '22');
- INSERT INTO n SELECT * FROM n; # 把数据复制一遍重新插入
- # 删除数据
- DELETE FROM n WHERE id = 2;
- # 更改数据
- UPDATE n SET name = 'tom' WHERE id = 2;
- # 数据查找
- SELECT * FROM n WHERE name LIKE '%h%';
- # 数据排序(反序)
- SELECT * FROM n ORDER BY name, id DESC ;
复制代码 3.5.5 键
- # 添加主键
- ALTER TABLE n ADD PRIMARY KEY (id);
- ALTER TABLE n ADD CONSTRAINT pk_n PRIMARY KEY (id); # 主键只有一个,所以定义键名似乎也没有什么用
- # 删除主键
- ALTER TABLE n DROP PRIMARY KEY ;
- # 添加外键
- ALTER TABLE m ADD FOREIGN KEY (id) REFERENCES n(id); # 自动生成键名m_ibfk_1
- ALTER TABLE m ADD CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES n(id); # 使用定义的键名fk_id
- # 删除外键
- ALTER TABLE m DROP FOREIGN KEY `fk_id`;
- # 修改外键
- ALTER TABLE m DROP FOREIGN KEY `fk_id`, ADD CONSTRAINT fk_id2 FOREIGN KEY (id) REFERENCES n(id); # 删除之后从新建
- # 添加唯一键
- ALTER TABLE n ADD UNIQUE (name);
- ALTER TABLE n ADD UNIQUE u_name (name);
- ALTER TABLE n ADD UNIQUE INDEX u_name (name);
- ALTER TABLE n ADD CONSTRAINT u_name UNIQUE (name);
- CREATE UNIQUE INDEX u_name ON n(name);
- # 添加索引
- ALTER TABLE n ADD INDEX (age);
- ALTER TABLE n ADD INDEX i_age (age);
- CREATE INDEX i_age ON n(age);
- # 删除索引或唯一键
- DROP INDEX u_name ON n;
- DROP INDEX i_age ON n;
复制代码 3.5.6 视图
- # 创建视图
- CREATE VIEW v AS SELECT id, name FROM n;
- CREATE VIEW v(id, name) AS SELECT id, name FROM n;
- # 查看视图(与表操作类似)
- SELECT * FROM v;
- DESC v;
- # 查看创建视图语句
- SHOW CREATE VIEW v;
- # 更改视图
- CREATE OR REPLACE VIEW v AS SELECT name, age FROM n;
- ALTER VIEW v AS SELECT name FROM n ;
- # 删除视图
- DROP VIEW IF EXISTS v;
复制代码 3.5.7 联接
- # 内联接
- SELECT * FROM m INNER JOIN n ON m.id = n.id;
- # 左外联接
- SELECT * FROM m LEFT JOIN n ON m.id = n.id;
- # 右外联接
- SELECT * FROM m RIGHT JOIN n ON m.id = n.id;
- # 交叉联接
- SELECT * FROM m CROSS JOIN n; # 标准写法
- SELECT * FROM m, n;
- # 类似全连接full join的联接用法
- SELECT id,name FROM m
- UNION
- SELECT id,name FROM n;
复制代码 3.5.8 函数
- # 聚合函数
- SELECT count(id) AS total FROM n; # 总数
- SELECT sum(age) AS all_age FROM n; # 总和
- SELECT avg(age) AS all_age FROM n; # 平均值
- SELECT max(age) AS all_age FROM n; # 最大值
- SELECT min(age) AS all_age FROM n; # 最小值
- # 数学函数
- SELECT abs(-5); # 绝对值
- SELECT bin(15), oct(15), hex(15); # 二进制,八进制,十六进制
- SELECT pi(); # 圆周率3.141593
- SELECT ceil(5.5); # 大于x的最小整数值6
- SELECT floor(5.5); # 小于x的最大整数值5
- SELECT greatest(3,1,4,1,5,9,2,6); # 返回集合中最大的值9
- SELECT least(3,1,4,1,5,9,2,6); # 返回集合中最小的值1
- SELECT mod(5,3); # 余数2
- SELECT rand(); # 返回0到1内的随机值,每次不一样
- SELECT rand(5); # 提供一个参数(种子)使RAND()随机数生成器生成一个指定的值。
- SELECT round(1415.1415); # 四舍五入1415
- SELECT round(1415.1415, 3); # 四舍五入三位数1415.142
- SELECT round(1415.1415, -1); # 四舍五入整数位数1420
- SELECT truncate(1415.1415, 3); # 截短为3位小数1415.141
- SELECT truncate(1415.1415, -1); # 截短为-1位小数1410
- SELECT sign(-5); # 符号的值负数-1
- SELECT sign(5); # 符号的值正数1
- SELECT sqrt(9); # 平方根3
- SELECT sqrt(9); # 平方根3
- # 字符串函数
- SELECT concat('a', 'p', 'p', 'le'); # 连接字符串-apple
- SELECT concat_ws(',', 'a', 'p', 'p', 'le'); # 连接用','分割字符串-a,p,p,le
- SELECT insert('chinese', 3, 2, 'IN'); # 将字符串'chinese'从3位置开始的2个字符替换为'IN'-chINese
- SELECT left('chinese', 4); # 返回字符串'chinese'左边的4个字符-chin
- SELECT right('chinese', 3); # 返回字符串'chinese'右边的3个字符-ese
- SELECT substring('chinese', 3); # 返回字符串'chinese'第三个字符之后的子字符串-inese
- SELECT substring('chinese', -3); # 返回字符串'chinese'倒数第三个字符之后的子字符串-ese
- SELECT substring('chinese', 3, 2); # 返回字符串'chinese'第三个字符之后的两个字符-in
- SELECT trim(' chinese '); # 切割字符串' chinese '两边的空字符-'chinese'
- SELECT ltrim(' chinese '); # 切割字符串' chinese '两边的空字符-'chinese '
- SELECT rtrim(' chinese '); # 切割字符串' chinese '两边的空字符-' chinese'
- SELECT repeat('boy', 3); # 重复字符'boy'三次-'boyboyboy'
- SELECT reverse('chinese'); # 反向排序-'esenihc'
- SELECT length('chinese'); # 返回字符串的长度-7
- SELECT upper('chINese'), lower('chINese'); # 大写小写 CHINESE chinese
- SELECT ucase('chINese'), lcase('chINese'); # 大写小写 CHINESE chinese
- SELECT position('i' IN 'chinese'); # 返回'i'在'chinese'的第一个位置-3
- SELECT position('e' IN 'chinese'); # 返回'i'在'chinese'的第一个位置-5
- SELECT strcmp('abc', 'abd'); # 比较字符串,第一个参数小于第二个返回负数- -1
- SELECT strcmp('abc', 'abb'); # 比较字符串,第一个参数大于第二个返回正数- 1
- # 时间函数
- SELECT current_date, current_time, now(); # 2018-01-13 12:33:43 2018-01-13 12:33:43
- SELECT hour(current_time), minute(current_time), second(current_time); # 12 31 34
- SELECT year(current_date), month(current_date), week(current_date); # 2018 1 1
- SELECT quarter(current_date); # 1
- SELECT monthname(current_date), dayname(current_date); # January Saturday
- SELECT dayofweek(current_date), dayofmonth(current_date), dayofyear(current_date); # 7 13 13
- # 控制流函数
- SELECT if(3>2, 't', 'f'), if(3<2, 't', 'f'); # t f
- SELECT ifnull(NULL, 't'), ifnull(2, 't'); # t 2
- SELECT isnull(1), isnull(1/0); # 0 1 是null返回1,不是null返回0
- SELECT nullif('a', 'a'), nullif('a', 'b'); # null a 参数相同或成立返回null,不同或不成立则返回第一个参数
- SELECT CASE 2
- WHEN 1 THEN 'first'
- WHEN 2 THEN 'second'
- WHEN 3 THEN 'third'
- ELSE 'other'
- END ; # second
- # 系统信息函数
- SELECT database(); # 当前数据库名-test
- SELECT connection_id(); # 当前用户id-306
- SELECT user(); # 当前用户-root@localhost
- SELECT version(); # 当前mysql版本
- SELECT found_rows(); # 返回上次查询的检索行数
复制代码 3.5.9 用户
- # 增加用户
- CREATE USER 'test'@'localhost' IDENTIFIED BY 'test';
- INSERT INTO mysql.user(Host, User, Password) VALUES ('localhost', 'test', Password('test')); # 在用户表中插入用户信息,直接操作User表不推荐
- # 删除用户
- DROP USER 'test'@'localhost';
- DELETE FROM mysql.user WHERE User='test' AND Host='localhost';
- FLUSH PRIVILEGES ;
- # 更改用户密码
- SET PASSWORD FOR 'test'@'localhost' = PASSWORD('test');
- UPDATE mysql.user SET Password=Password('t') WHERE User='test' AND Host='localhost';
- FLUSH PRIVILEGES ;
- # 用户授权
- GRANT ALL PRIVILEGES ON *.* TO test@localhost IDENTIFIED BY 'test';
- # 授予用'test'密码登陆成功的test@localhost用户操作所有数据库的所有表的所有的权限
- FLUSH PRIVILEGES ; # 刷新系统权限表,使授予权限生效
- # 撤销用户授权
- REVOKE DELETE ON *.* FROM 'test'@'localhost'; # 取消该用户的删除权限
复制代码 3.5.10存储过程
- # 创建存储过程
- DELIMITER // # 无参数
- CREATE PROCEDURE getDates()
- BEGIN
- SELECT * FROM test ;
- END //
- CREATE PROCEDURE getDates_2(IN id INT) # in参数
- BEGIN
- SELECT * FROM test WHERE a = id;
- END //
- CREATE PROCEDURE getDates_3(OUT sum INT) # out参数
- BEGIN
- SET sum = (SELECT count(*) FROM test);
- END //
- CREATE PROCEDURE getDates_4(INOUT i INT) # inout参数
- BEGIN
- SET i = i + 1;
- END //
- DELIMITER ;
- # 删除存储过程
- DROP PROCEDURE IF EXISTS getDates;
- # 修改存储过程的特性
- ALTER PROCEDURE getDates MODIFIES SQL DATA ;
- # 修改存储过程语句(删除再重建)略
- # 查看存储过程
- SHOW PROCEDURE STATUS LIKE 'getDates'; # 状态
- SHOW CREATE PROCEDURE getDates_3; # 语句
- # 调用存储过程
- CALL getDates();
- CALL getDates_2(1);
- CALL getDates_3(@s);
- SELECT @s;
- SET @i = 1;
- CALL getDates_4(@i);
- SELECT @i; # @i = 2
复制代码 3.5.11 其他语句
- # 查看所有的表信息(包括视图)
- SHOW TABLE STATUS;
复制代码 3.5.12 其他
- # 数据库备份
- mysqldump -u root -p db_name > file.sql
- mysqldump -u root -p db_name table_name > file.sql
- # 数据库还原
- mysql -u root -p < C:\file.sql
复制代码 4.阿里云
4.1 什么是服务器
服务器是一种专用的计算机或系统软件,旨在提供各种网络服务,如数据存储、文件共享、电子邮件、数据库管理和互联网访问等。服务器通常具有较高的处理惩罚能力、存储容量和网络带宽,以满足多个客户端(如个人电脑、移动设备或其他服务器)的需求。
4.2 购买阿里云服务器
阿里云官网阿里云-计算,为了无法计算的价值 (aliyun.com)
登陆进入官网,选择产物-云服务器,选择云服务器ECS。
4.3 服务器选择操纵系统
按照自己的需求购买服务器ECS即可。这里我实例规格选择的是基础设置(2vCPU2GiB),镜像选择的是Ubuntu22.04 64位,按需选择即可。
4.4 访问操纵系统
4.4.1 xshell举行访问
前提条件
1.阿里云 ECS 服务器的 IP 地址
2.服务器的用户名和密码 或 SSH 密钥对
3.Xshell 软件(已安装在你的电脑上)
步调:
1.打开 Xshell
打开已经安装的 Xshell 软件。
2.创建新会话
在 Xshell 主界面,点击左上角的“新建”按钮,创建一个新的会话。
3.设置会话
在弹出的“新建会话属性”窗口中,设置以下信息:
•名称:为会话起一个名字(比如“阿里云 ECS”)。
•主机:输入阿里云 ECS 服务器的公有 IP 地址。(在阿里云服务器-控制台-设置信息中)
•协议:选择 SSH。
•端口号:默认环境下,SSH 的端口号是 22。
4.用户身份验证
切换到“用户身份验证”标签,设置以下信息:
•用户名:输入你登录服务器的用户名(默认一般是 root 或者其他你设置的用户名)。
•认证方法:
•如果使用密码登录,选择“密码”,然后输入你的密码。
•如果使用密钥对登录,选择“公钥”,并点击“设置”按钮选择你的私钥文件。
5.生存设置并毗连
点击“确定”生存会话设置,然后在 Xshell 主界面中双击刚创建的会话,开始毗连到服务器。
6.接受主机密钥
第一次毗连时,Xshell 会提示你接受服务器的主机密钥。确认信息无误后,点击“接受并生存”按钮。
7.成功毗连
如果全部设置正确,你将会成功毗连到阿里云 ECS 服务器,并看到服务器的命令行提示符。现在即可在 Xshell 中输入命令并对服务器举行操纵。
4.4.2 网址访问
再购买实例后,可以通过网址对操纵系统举行访问。
如图所示,点击控制台,进入控制台后,可以看到购买的实例。
点击远程毗连-通过Workbench远程毗连,即可访问实例。
5.部署mysql
5.1命令安装mysql
5.1.1 更新包列表并安装 MySQL
1.更新包列表:sudo apt update
2.安装 MySQL 服务器:sudo apt install mysql-server
5.1.2 启动 MySQL 服务并检查状态
1.确认 MySQL 服务已经启动:sudo systemctl status mysql
5.1.3 运行 MySQL 安全安装脚本
1.设置 MySQL 安全设置:sudo mysql_secure_installation
按照提示完成以下设置:
•设置 root 用户密码
•移除匿名用户
•克制 root 用户远程登录
•删除测试数据库
•重新加载权限表
5.2对数据库举行设置
5.2.1 编辑 MySQL 设置文件
1.打开 MySQL 设置文件举行编辑:sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
5.2.2 修改根本设置选项
1.在 mysqld.cnf 文件中,根据需要添加或修改以下设置选项:
- [mysqld]
- port = 3306
- bind-address = 0.0.0.0 # 如果需要远程访问,请将此值设为 0.0.0.0 或具体的 IP 地址
- max_connections = 100
- default-storage-engine = INNODB
- character-set-server = utf8mb4
- collation-server = utf8mb4_unicode_ci
复制代码 5.2.3 重启 MySQL 服务并创建用户和数据库
1.重启 MySQL 服务使设置见效:sudo systemctl restart mysql
2.通过 MySQL 命令行客户端毗连到数据库并创建新的用户和数据库:sudo mysql -u root -p
3.在 MySQL 提示符下运行以下命令创建数据库和用户:
- CREATE DATABASE your_database_name;
- CREATE USER 'your_username'@'localhost' IDENTIFIED BY 'your_password';
- GRANT ALL PRIVILEGES ON your_database_name.* TO 'your_username'@'localhost';
- FLUSH PRIVILEGES;
复制代码 6.部署区块链
6.1前期环境设置
1.Java安装
- $ sudo add-apt-repository ppa:openjdk-r/ppa
- $ sudo apt-get update
- $ sudo apt-get install openjdk-8-jdk
- # 查询Java版本
- $ java -version
复制代码 2.安装MySQL数据库(建议安装MySQL5)
2.1添加MySQL源
sudo vim /etc/apt/sources.list.d/mysql.list
添加如下内容:
- deb http://repo.mysql.com/apt/ubuntu/ bionic mysql-apt-config
- deb http://repo.mysql.com/apt/ubuntu/ bionic mysql-5.7
- deb http://repo.mysql.com/apt/ubuntu/ bionic mysql-tools
- deb-src http://repo.mysql.com/apt/ubuntu/ bionic mysql-5.7
复制代码 更新
sudo apt update
执行过程中大概会出现如下错误:
- W: GPG error: http://repo.mysql.com/apt/ubuntu bionic InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 467B942D3A79BD29
- E: The repository 'http://repo.mysql.com/apt/ubuntu bionic InRelease' is not signed.
- N: Updating from such a repository can't be done securely, and is therefore disabled by default.
- N: See apt-secure(8) manpage for repository creation and user configuration details.
复制代码 执行如下命令即可,467B942D3A79BD29根据实际环境替换:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 467B942D3A79BD29
重新执行更新:
sudo apt update
2.2安装 MySQL
检察支持的 MySQL 版本:sudo apt-cache policy mysql-server
安装 MySQL 5.7 版本客户端和服务端:sudo apt install mysql-client=5.7.40-1ubuntu18.04
3.Python安装
- // 添加仓库,回车继续
- sudo add-apt-repository ppa:deadsnakes/ppa
- // 安装python 3.6
- sudo apt-get install -y python3.6
- sudo apt-get install -y python3-pip
复制代码 4.PyMySQL安装
- sudo apt-get install -y python3-pip
- sudo pip3 install PyMySQL
复制代码
6.2区块链安装
6.2.1下载包
1.获取部署安装包
- wget https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/releases/download/v1.5.5/webase-deploy.zip
复制代码 2.解压安装包
- apt install unzip
- unzip webase-deploy.zip
复制代码 3.进入目次
4.修改设置(如图所示)
6.2.2一键部署
- # 部署并启动所有服务
- python3 deploy.py installAll
复制代码 看到如下提示即表示部署成功:
- ...
- ============================================================
- _ _ ______ ___ _____ _____
- | | | | | ___ \/ _ \/ ___| ___|
- | | | | ___| |_/ / /_\ \ `--.| |__
- | |/\| |/ _ | ___ | _ |`--. | __|
- \ /\ | __| |_/ | | | /\__/ | |___
- \/ \/ \___\____/\_| |_\____/\____/
- ...
- ...
- ============================================================
- ============== deploy has completed ==============
- ============================================================
- ============== webase-web version v1.5.5 ========
- ============== webase-node-mgr version v1.5.5 ========
- ============== webase-sign version v1.5.3 ========
- ============== webase-front version v1.5.5 ========
- ============================================================
复制代码 若出现如下错误:error! JAVA_HOME has not been configured!
解决:
- cd /usr/lib/jvm/
- ls
- export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
- export JRE_HOME=${JAVA_HOME}/jre
- export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
- export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:$PATH
- echo $JAVA_HOME
复制代码 重新运行python3 deploy.py installAll
服务部署后,需要对各服务举行启停操纵,可以使用以下命令:
- 部署并启动所有服务 python3 deploy.py installAll
- 停止一键部署的所有服务 python3 deploy.py stopAll
- 启动一键部署的所有服务 python3 deploy.py startAll# 各子服务启停
- 启动FISCO-BCOS节点: python3 deploy.py startNode
- 停止FISCO-BCOS节点: python3 deploy.py stopNode
- 启动WeBASE-Web: python3 deploy.py startWeb
- 停止WeBASE-Web: python3 deploy.py stopWeb
- 启动WeBASE-Node-Manager: python3 deploy.py startManager
- 停止WeBASE-Node-Manager: python3 deploy.py stopManager
- 启动WeBASE-Sign: python3 deploy.py startSign
- 停止WeBASE-Sign: python3 deploy.py stopSign
- 启动WeBASE-Front: python3 deploy.py startFront
- 停止WeBASE-Front: python3 deploy.py stopFront# 可视化部署
- 部署并启动可视化部署的所有服务 python3 deploy.py installWeBASE
- 停止可视化部署的所有服务 python3 deploy.py stopWeBASE
- 启动可视化部署的所有服务 python3 deploy.py startWeBASE
复制代码 6.2.3区块链设置
区块链设置文件为common.properties
在终端输入以下命令进入区块链设置文件:
- cd webase-deploy
- vi common.properties
复制代码
在node.counts中可以修改区块链的节点个数(默认为2个)。
6.2.4开放端口
webase平台的访问地址为:http://localhost:5000
使用云服务厂商的服务器时,需要开通网络安全组的对应端口。如开放webase使用的5000端口。
在阿里云服务器中开放5000端口
在服务器控制台中,点击安全组,进入安全组。
选择管理规则,手动添加5000端口。
通过云服务器的公网ip:5000即可访问webase平台。
6.3项目部署
6.3.1编写智能合约
在Webase管理平台编写智能合约VotingSystem.sol智能合约。在VotingSystem智能合约中,该合约负责存储和检索投票记录,本质上充当了投票详细信息的数据库或账本。合约允许存储与特定运动相关的投票,并提供按投票标识符或运动名称检索这些投票的功能。以下是合约功能的形貌:
1.投票存储和检索:合约存储投票记录,包罗消息、投票本身、投票的SM3哈希值、投票人的公钥以及与投票相关的运动名称。这些详细信息封装在一个VoteRecord布局体中。
2.基于运动的投票管理:合约维护运动名称与相关投票之间的映射关系,如许可以将特定运动下的全部投票举行分组并检索。
3.功能:
•storeVote:此函数用于将新投票存储到系统中。它吸收投票详细信息作为输入,并将投票与相关运动相关联。
•getVoteByVote:此函数通过投票标识符检索特定投票记录,并返回与该投票相关的全部详细信息。
•getVotesByActivityName:此函数允许用户检索与特定运动名称相关的全部投票记录,并返回包含该运动下全部投票详细信息的 VoteRecord 布局体数组。

AdvancedVotingSystem.sol代码如下:
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.6.0;
- pragma experimental ABIEncoderV2;
- contract AdvancedVotingSystem {
- struct VoteRecord {
- string vote;
- string sm3_vote;
- string ringSign_publicKey;
- string vote_time;
- string publicKey_id;
- string activity_name;
- }
- mapping(string => VoteRecord) private votes;
- mapping(string => string[]) private activityVotes;
- // 存储投票记录
- function storeVote(
- string memory _vote,
- string memory _sm3_vote,
- string memory _ringSign_publicKey,
- string memory _vote_time,
- string memory _publicKey_id,
- string memory _activity_name
- ) public {
- VoteRecord memory newVote = VoteRecord({
- vote: _vote,
- sm3_vote: _sm3_vote,
- ringSign_publicKey: _ringSign_publicKey,
- vote_time: _vote_time,
- publicKey_id: _publicKey_id,
- activity_name: _activity_name
- });
- votes[_vote] = newVote;
- activityVotes[_activity_name].push(_vote);
- }
- // 通过 vote 查询对应的投票记录
- function getVoteByVote(string memory _vote) public view returns (string memory, string memory, string memory, string memory, string memory, string memory) {
- require(bytes(votes[_vote].vote).length != 0, "Vote not found");
- VoteRecord memory voteRecord = votes[_vote];
- return (voteRecord.vote, voteRecord.sm3_vote, voteRecord.ringSign_publicKey, voteRecord.vote_time, voteRecord.publicKey_id, voteRecord.activity_name);
- }
- // 通过 activity_name 查询所有该 activity_name 下的投票记录
- function getVotesByActivityName(string memory _activity_name) public view returns (VoteRecord[] memory) {
- string[] memory voteKeys = activityVotes[_activity_name];
- VoteRecord[] memory results = new VoteRecord[](voteKeys.length);
- for (uint i = 0; i < voteKeys.length; i++) {
- results[i] = votes[voteKeys[i]];
- }
- return results;
- }
- }
复制代码 在合约编写完毕之后,接下来便是对合约举行编译的环节。编译完成后,将天生的字节码发送至区块链网络中的相关节点,执行这一操纵会触发生意业务的发送。随着生意业务的成功,合约正式部署在区块链上,这时就可以举行选票信息的存储与查询操纵。通过这种方式,确保选票信息的高效、安全存储,而且可以随时通过合约查询到相关信息,从而保证了电子投票系统的透明性和可信度。

在完成合约编译并发送生意业务之后,可看到生意业务回执。这一回执提供了对生意业务状态的详细记录。通过分析回执中的数据,我们能够确认选票信息是否已成功存储在区块链上,并获得相关的生意业务细节。这一过程不但增强了系统的透明度,还为后续的数据查询和验证提供了坚实的基础。

在查询投票记录的过程中,起首需要通过投票标识符调用合约中的查询函数。该函数会根据传入的标识符在合约中查找对应的投票记录。查询操纵完成后,合约会返回与该投票记录相关的全部详细信息,如消息内容、投票信息、SM3 哈希值、公钥以及运动名称等。

通过这种方式,用户能够快速、高效地获取特定投票的详细信息,确保全部投票记录都能被正确地存储和查询,从而进一步增强电子投票系统的透明度和可信度。在完成查询操纵后,用户将获得一组与投票记录相关的返回值,这些返回值提供了对投票数据的完备形貌。通过分析这些返回值,用户可以确认投票记录是否正确存储在区块链上,并获取相关的详细信息。这一过程不但保证了投票记录的可追溯性,还为后续的审计和验证提供了有力支持。

在通过运动名称查询全部关联的投票记录时,需要调用合约中的相应查询函数。该函数会根据传入的运动名称在合约中查找全部与之相关的投票标识符,并进一步检索每个投票记录的详细信息。查询操纵完成后,合约会返回与该运动名称相关的全部投票记录的数组,其中包含每条投票记录的完备信息。

通过这种方式,用户可以轻松地获取特定运动下的全部投票信息,确保每一条投票记录都能被正确分类和检索,提拔电子投票系统的操纵效率和信息管理能力。在查询完成后,用户将收到一个包含多个投票记录的返回数组,这些数组提供了该运动下全部投票的详细环境。通过分析这些返回结果,用户可以全面掌握该运动的投票环境,为后续的统计、分析和验证提供正确的数据支持。这一过程有效地保证了投票数据的完备性和可靠性。

用户可以通过输入运动名称来查询该运动下全部候选人的得票数据。合约中的查询函数会根据运动名称自动检索与之相关的全部投票记录,并对每个候选人的得票数举行统计。以下是计票智能合约代码,展示了这一统计过程:
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.6.0;
- pragma experimental ABIEncoderV2;
- contract VotingSystem3 {
- struct VoteRecord {
- string activityName;
- string vote;
- string candidateName;
- }
- // 存储每个活动对应的所有投票记录
- mapping(string => VoteRecord[]) private activityVotes;
- // 存储每个活动下每个候选人对应的投票数量
- mapping(string => mapping(string => uint)) private candidateVoteCount;
- // 存储每个活动的总投票数
- mapping(string => uint) private totalVotesCount;
- // 存储投票记录
- function storeVote(
- string memory _activityName,
- string memory _vote,
- string memory _candidateName
- ) public {
- VoteRecord memory newVote = VoteRecord({
- activityName: _activityName,
- vote: _vote,
- candidateName: _candidateName
- });
- activityVotes[_activityName].push(newVote);
- candidateVoteCount[_activityName][_candidateName]++;
- totalVotesCount[_activityName]++;
- }
- // 根据活动名称查询候选人的票数,并按得票数排序
- function getVotesByActivityName(string memory _activityName) public view returns (string memory) {
- uint totalVotes = totalVotesCount[_activityName];
- require(totalVotes > 0, "未找到该活动的投票记录");
- string memory result = string(abi.encodePacked("活动名称: ", _activityName, "\n总投票数: ", uintToString(totalVotes), "\n\n"));
- // 统计候选人及其票数
- string[] memory candidates = new string[](activityVotes[_activityName].length);
- uint[] memory votesCount = new uint[](activityVotes[_activityName].length);
- uint candidateIndex = 0;
- for (uint i = 0; i < activityVotes[_activityName].length; i++) {
- string memory candidateName = activityVotes[_activityName][i].candidateName;
-
- // 检查是否已记录该候选人
- bool alreadyRecorded = false;
- for (uint j = 0; j < candidateIndex; j++) {
- if (keccak256(bytes(candidates[j])) == keccak256(bytes(candidateName))) {
- alreadyRecorded = true;
- break;
- }
- }
-
- // 如果未记录,则添加到数组中
- if (!alreadyRecorded) {
- candidates[candidateIndex] = candidateName;
- votesCount[candidateIndex] = candidateVoteCount[_activityName][candidateName];
- candidateIndex++;
- }
- }
- // 按票数排序
- for (uint i = 0; i < candidateIndex; i++) {
- for (uint j = i + 1; j < candidateIndex; j++) {
- if (votesCount[i] < votesCount[j]) {
- // 交换票数
- uint tempVotes = votesCount[i];
- votesCount[i] = votesCount[j];
- votesCount[j] = tempVotes;
- // 交换候选人名字
- string memory tempCandidate = candidates[i];
- candidates[i] = candidates[j];
- candidates[j] = tempCandidate;
- }
- }
- }
- // 生成最终结果
- for (uint i = 0; i < candidateIndex; i++) {
- string memory percentage = calculatePercentage(votesCount[i], totalVotes);
- result = string(abi.encodePacked(result, "候选人: ", candidates[i], "\n票数: ", uintToString(votesCount[i]), "\n得票率: ", percentage, "%\n\n"));
- }
- return result;
- }
- // 计算百分比
- function calculatePercentage(uint _part, uint _whole) internal pure returns (string memory) {
- uint percentage = (_part * 100) / _whole;
- return uintToString(percentage);
- }
- // uint 转换为 string
- function uintToString(uint v) internal pure returns (string memory) {
- if (v == 0) {
- return "0";
- }
- uint maxlength = 100;
- bytes memory reversed = new bytes(maxlength);
- uint i = 0;
- while (v != 0) {
- uint remainder = v % 10;
- v = v / 10;
- reversed[i++] = byte(uint8(48 + remainder));
- }
- bytes memory s = new bytes(i);
- for (uint j = 0; j < i; j++) {
- s[j] = reversed[i - j - 1];
- }
- return string(s);
- }
- }
复制代码
完成候选人得票数据查询后,用户将收到一份生意业务回执。回执中详细记录了查询过程中涉及的全部操纵步调和返回结果。每位候选人的得票数及其统计信息都将在回执中展示,确保用户能够全面掌握查询结果的细节。这份回执不但为用户提供了生意业务的透明记录,还为后续的数据考核和验证提供了可靠依据,进一步增强了投票系统的可信度和安全性。

在Webase平台上,开辟者可以通过合约的多种功能实现复杂的业务逻辑,例如投票系统中的投票记录存储与查询。平台的强大功能确保了数据的安全性和透明性,每一步操纵都在区块链上得到精确记录和验证。通过生意业务回执的分析,开辟者可以确认每笔生意业务的成功与否,并获取详细的生意业务信息。这种全流程的管理方式不但进步了系统的可靠性,还为后续的运维和审计提供了有力保障。

6.3.2编译运行
在webase平台上点击编译,并点击部署,即部署成功,部署成功后,点击发生意业务即可举行存储与读取。再编译和部署完智能合约后,可以得到合约的地址。
6.3.3导出项目
1.点击右上角导出Java项目后,即可导出一个自命名的Java项目

2.在IDEA中打开导出的Java项目
项目布局如图:

这是一个gradle构建的SpringBoot项目。
3.编写Controller层来测试智能合约中的方法
TestController.java测试合约的add和get方法是否调用成功
- package org.example.demo2.controller;
- import org.example.demo2.model.bo.VoteAddCandidateInputBO;
- import org.example.demo2.model.bo.VoteGetCandidateInfoInputBO;
- import org.example.demo2.service.VoteService;
- import org.fisco.bcos.sdk.v3.transaction.model.dto.CallResponse;
- import org.fisco.bcos.sdk.v3.transaction.model.dto.TransactionResponse;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RestController;
- @RestController
- public class TestController {
- @Autowired
- private VoteService voteService;
- @PostMapping("/addCandidate")
- public TransactionResponse set(@RequestBody VoteAddCandidateInputBO vai) throws Exception {
- TransactionResponse result = voteService.addCandidate(vai);
- return result;
- }
- @GetMapping("/getCandidateInfo")
- public CallResponse get(@RequestBody VoteGetCandidateInfoInputBO vgi) throws Exception {
- CallResponse response = voteService.getCandidateInfo(vgi);
- return response;
- }
- }
复制代码 
4.启动项目
项目启动成功如图所示:

5.Postman测试add和get方法
下图为add方法:

下图为get方法:

调用方法成功。
7.毗连mysql
7.1navicat毗连本地mysql
打开navicat,点击毗连,选择mysql
输入账号和密码
点击测试
如果成功,则点击确定,毗连成功
7.2navicat使用ssh毗连服务器mysql
打开navicat,点击毗连,选择mysql
点击ssh,输入云账号和密码
点击毗连测试
如果navicat到ssh可以连通,说明ssh毗连成功
点击常规,输入云上数据库和密码举行毗连
点击测试
如果成功,则点击确定,毗连成功
7.3springboot毗连本地myaql
设置application.properties
- #加载驱动
- spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
- #数据库ip和端口
- spring.datasource.url=jdbc:mysql://127.0.0.1:3306/voteDataBase?useUnicode=true&useSSL=false&allowLoadLocalInfile=false&autoReconnect=true&failOverReadOnly=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=30000
- #账号
- spring.datasource.username=root
- #密码
- spring.datasource.password=123456
复制代码 7.4springboot使用ssh毗连服务器mysql
7.4.1添加依赖
- <dependency>
- <groupId>com.jcraft</groupId>
- <artifactId>jsch</artifactId>
- <version>0.1.55</version>
- </dependency>
复制代码 7.4.2编写设置类
SshConfiguration.java
- package com.mc.aliyun;
- import com.mc.aliyun.SshProperties;
- import jakarta.annotation.PreDestroy;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.weaving.LoadTimeWeaverAware;
- import org.springframework.instrument.classloading.LoadTimeWeaver;
- import com.jcraft.jsch.JSch;
- import com.jcraft.jsch.JSchException;
- import com.jcraft.jsch.Session;
- import lombok.extern.slf4j.Slf4j;
- @Configuration
- @EnableConfigurationProperties(SshProperties.class)
- @ConditionalOnProperty(prefix = "ssh", value = "enabled", havingValue = "true", matchIfMissing = false)
- @Slf4j
- // 实现 LoadTimeWeaverAware 接口是因为需要 SSH 正向代理需要在EntityManagerFactory加载前运行
- public class SshConfiguration implements LoadTimeWeaverAware {
- private final Session session;
- public SshConfiguration(SshProperties sshProperties) {
- Session session = null;
- try {
- // 可以自行为 JSch 添加日志,需要实现 com.jcraft.jsch.Logger 接口
- // JSch.setLogger(new JSchLogger())
- session = new JSch().getSession(sshProperties.getUsername(), sshProperties.getHost(), sshProperties.getPort());
- session.setConfig("StrictHostKeyChecking", "no");
- session.setPassword(sshProperties.getPassword());
- session.connect();
- SshProperties.Forward forward = sshProperties.getForward();
- if (forward != null) {
- session.setPortForwardingL(forward.getFromHost(), forward.getFromPort(), forward.getToHost(), forward.getToPort());
- log.info("{}:{} -> {}:{}", forward.getFromHost(), forward.getFromPort(), forward.getToHost(), forward.getToPort());
- }
- } catch (JSchException e) {
- log.error("ssh " + sshProperties.getHost() + " failed.", e);
- }
- this.session = session;
- }
- @PreDestroy
- // 配置销毁时,断开 SSH 链接
- public void disconnect() {
- if (session != null) {
- session.disconnect();
- }
- }
- @Override
- public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
- }
- }
复制代码 SshProperties.java
- package com.mc.aliyun;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import lombok.Getter;
- import lombok.Setter;
- import lombok.ToString;
- @Getter
- @Setter
- @ToString(exclude="password")
- @ConfigurationProperties(prefix="ssh")
- public class SshProperties {
- private String host;
- private Integer port;
- private String username;
- private String password;
- private Forward forward;
- @Getter
- @Setter
- @ToString
- public static class Forward {
- private String fromHost;
- private Integer fromPort;
- private String toHost;
- private Integer toPort;
- }
- }
复制代码 7.4.3 编写设置文件application.properties
- #加载驱动
- spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
- #连接数据库
- spring.datasource.url=jdbc:mysql://127.0.0.1:3307/voteDataBase?useUnicode=true&useSSL=false&allowLoadLocalInfile=false&autoReconnect=true&failOverReadOnly=false&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=30000
- #spring.datasource.url=jdbc:mysql://127.0.0.1:3306/gm
- #账号
- spring.datasource.username=root
- #密码
- spring.datasource.password=123456
- #开启ssh配置
- ssh.enabled=true
- #服务器地址
- ssh.host=***.***.***.***
- #连接服务器端口号
- ssh.port=22
- #服务器账号
- ssh.username=root
- #服务器密码
- ssh.password=Zzh123456
- #接收到数据库地址
- ssh.forward.from_host=localhost
- #接收到数据库端口
- ssh.forward.from_port=3307
- #来自于数据库地址
- ssh.forward.to_host=localhost
- #来自于数据库端口
- ssh.forward.to_port=3306
复制代码 7.3.4 原理
服务器上数据库3306端口会映射到本机3307端口上
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |