-
一、环境介绍1. 软件环境类别版本下载链接备注OSopenEuler 20.03 (LTS)cid:link_1操作系统BenchmarkSQL5.0cid:link_3驱动版本:postgresql-9.3-1102.jdbc41.jar模拟TPCC压力的程序驱动为程序自带的pg驱动Golanggo1.18 linux/arm64cid:link_5cid:link_2cid:link_4模拟应用连接的程序openGauss3.0.0cid:link_0数据库2. 硬件环境主机CPU规格硬盘职责node1Kunpeng-920虚拟机16c/64g通用型SSD主库node2Kunpeng-920虚拟机16c/64g通用型SSD同步备库go程序node3Kunpeng-920虚拟机16c/64g通用型SSD异步备库BenchmarkSQL程序3. 架构图二、测试场景1. go程序多IP连接测试RTO原理:CM检测主库发生故障,不可访问时会自动选新主,go驱动通过target_session_attrs=read-write控制只连主库,通过SQL select sysdate,pg_is_in_recovery(); 查询结果时间戳查看RTOgo程序代码[root@cloud001-0003 go]# cat 1.go // Copyright © 2021 Bin Liu package main import ( "database/sql" "fmt" _ "gitee.com/opengauss/openGauss-connector-go-pq" "log" "os" "os/signal" "syscall" "time" ) /* 需要有访问dbe_perf.global_instance_time的权限 CREATE USER dbuser_monitor with login monadmin PASSWORD 'Mon@1234'; grant usage on schema dbe_perf to dbuser_monitor; grant select on dbe_perf.global_instance_time to dbuser_monitor; CGO_ENABLED=0 GOOS=linux GOARCH=arm64 */ var ( dsnExample = `DSN="postgres://gaussdb:secret@foo,bar,baz/mydb?sslmode=disable" DSN="postgres://gaussdb:secret@foo:1,bar:2,baz:3/mydb?sslmode=disable" DSN="user=gaussdb password=secret host=foo,bar,baz port=5432 dbname=mydb sslmode=disable" DSN="user=gaussdb password=secret host=foo,bar,baz port=5432,5432,5433 dbname=mydb sslmode=disable"` ) func main() { os.Setenv("DSN", "postgres://gaussdb:Enmo12345@172.16.0.65:26000,172.16.0.202:26000,172.16.0.193:26000/postgres?"+ "sslmode=disable&loggerLevel=debug&target_session_attrs=read-write") connStr := os.Getenv("DSN") if connStr == "" { fmt.Println("please define the env DSN. example:\n" + dsnExample) return } fmt.Println("DNS:", connStr) db, err := sql.Open("opengauss", connStr) if err != nil { log.Fatal(err) } var ( newTimer = time.NewTicker(1 * time.Second) doClose = make(chan struct{}, 1) ) go func() { for { select { case <-newTimer.C: if err := getNodeName(db); err != nil { fmt.Println(err) } case <-doClose: newTimer.Stop() return } } }() sigChan := make(chan os.Signal, 2) signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) //nolint:staticcheck defer signal.Stop(sigChan) <-sigChan doClose <- struct{}{} } func getNodeName(db *sql.DB) error { var err error // tx, err := db.Begin() // if err != nil { // return err // } // defer tx.Commit() var sysdate string var pgIsInRecovery bool var nodeName string err = db.QueryRow("select sysdate,pg_is_in_recovery();"). Scan(&sysdate, &pgIsInRecovery) if err != nil { return err } var channel string // err = db.QueryRow("select channel from pg_stat_get_wal_senders() limit 1 "). // Scan(&channel) fmt.Println(sysdate, nodeName, pgIsInRecovery, channel) // if err != nil { // return err // } return nil } 模拟数据库故障[omm@cloud001-0002 data]$ mv db1/ db1.bakgo程序连接数据库及重连时间时间差 ```s 2022/04/11 16:02:13.614273 connector.go:222: info dialing server host 172.16.0.65 port 26000 2022/04/11 16:02:20.683716 connector.go:145: debug find instance host 172.16.0.202 port 26000RTO时间7s ## 2. BenchmarkSQL多IP连接测试RTO > 原理:CM检测主库发生故障,不可访问时会自动选新主,jdbc驱动通过target_session_type=master控制只连主库,通过SQL 程序执行时间戳查看RTO **BenchmarkSQL模拟负载及重连时间**   - 时间差 ```s 16:02:13,561 [Thread-8] ERROR jTPCCTData : Unexpected SQLException in STOCK_LEVELsage: 153MB / 897MB 16:02:20,834 [Thread-57] FATAL jTPCCTerminal : Unexpected SQLException on rollback: This connection has been closed. RTO时间7.273s3. 数据库端观测时间数据库日志时间差2022-04-11 16:02:13.253 tid=1795056 StartAndStop ERROR: data path disc writable test failed, /opt/mogdb/data/data/db1. 2022-04-11 16:02:20.438 tid=1815697 LOG: failover msg from cm_server, data_dir :/opt/mogdb/data/data/db1 nodetype is 2 RTO时间7.185s总结在有负载情况(tpcc压测产生负载,数据库服务器CPU占用50%左右)进行主库宕机测试,以主库宕机为起始点,备库成功作为新主库启动成功为终止点RTO为7.185s以主库宕机为起始点,模拟TPCC压测的benchmarkSQL程序成功重新连接到新主库为终止点RTO为7.273s以主库宕机为起始点,模拟其它应用连接数据库的go程序成功重新连接到新主库为终止点7s由于go程序至精确到s,猜测实际时间为7.185s以上综上所述openGauss Cluster Manager RTO约为7s左右
-
系统介绍Mall4j是国内领先的电商商城系统源码提供商,是众多知名企业搭建商城的不二选择。Mall4j商城系统支持企业自营模式,招商模式,O2O门店模式,满足企业各个发展阶段的商业模式,全面覆盖微信商城、小程序商城、手机触屏版商城、苹果APP商城、安卓APP商城及PC端,统一的数据,能很大程度提高销售利润和提升服务质量,让您一次开店,全通路覆盖。Mall4j商城系统可以将企业的资源进行有效的整合,让商家的布局更加广泛、配套更加完善、管理更加成熟。另外,mall4j商城系统可以帮助企业集合各个渠道的资源,充分利用资源和渠道来提升商城的销量。还有多种营销功能:团购、秒杀、会员积分、优惠券、满减满折等营销玩法,把消费变成了一种“游戏”,有趣,有效果。系统亮点Mall4j商城系统功能亮点: 1、系统具备高效的管理功能:商品管理、会员管理、订单管理、统计管理、支付管理、门店管理、库存管理等管理功能; 2、灵活多样的营销赋能模式:满减、团购、秒杀、分销、积分、O2O、优惠券、套餐、赠品等营销方式; 3、多终端适配:支持PC、H5、小程序、APP(android、IOS)。Mall4j商城系统技术亮点:技术主流,使用最流行框架技术,没有过多的技术债务。提供全部源码,无封装无加密,没有license。更新升级方便,通过git私服进行代码合并更新。代码前后端分离,代码质量高注释清晰,方便二次开发。mall4j商城版本开源版银河版宇宙版白洞版业务模式B2CB2CB2B2CS2B2C适用群体个人、初学者自营店、小规模企业自营+入驻、中小型企业自营+供应商/商家入驻加密程度全开源,无加密提供全部源码,无加密提供全部源码,无加密提供全部源码,无加密服务内容商业授权AGPL3.0协议永久授权永久授权永久授权代码更新Gitee、Github更新Git私服更新Git私服更新Git私服更新企业售后群×√√√功能列表√√√√技术文档√√√√操作手册×√√√合同签约×√√√基础功能前后端分离√√√√Spring Cloud脚手架√××√Spring Boot脚手架√√√√权限管理√√√√完整下单流程√√√√小程序端√√√√H5端√√√√PC端×√√√App端(iOS、Android)×√√√后台管理移动端××√×后台管理PC端√√√√国际化×√√×高级功能多商家入驻√×√√供应商端×××√平台抽佣××√√PC端装修××√√移动端装修××√√优惠券×√√√满减满折×√√√拼团活动×√√√秒杀活动×√√√商品预售×√√√优惠套餐××√√赠品××√√分销模块×√√√会员管理×√√√积分商城×√√√虚拟商品××√√用户自提×√√×同城配送×√√×小程序直播×√√√客服系统(IM)×√√√进销存管理××√√客户标签与营销×√√√数据分析×√√√数据报表×√√√消息推送×√√√技术组件技术版本说明Spring Boot2.1.6.RELEASEMVC核心框架Spring Security oauth22.1.5.RELEASE认证和授权框架MyBatis3.5.0ORM框架MyBatisPlus3.1.0基于mybatis,使用lambda表达式的Swagger-UI2.9.2文档生产工具Hibernator-Validator6.0.17.Final验证框架redisson3.10.6对redis进行封装、集成分布式锁等hikari3.2.0数据库连接池log4j22.11.2更快的log日志工具fst2.57更快的序列化和反序列化工具orika1.5.4更快的bean复制工具lombok1.18.8简化对象封装工具hutool4.5.0更适合国人的java工具集swagger-bootstrap1.9.3基于swagger,更便于国人使用的swagger u工具版本jdk1.8+mysql5.7+redis3.2+技术架构SOA会通过ESB来作为系统和服务之间的通信桥梁,ESB本身还提供服务地址的管理、不同系统之间的 协议转化和数据格式转化等等。消费者不需要关心目标的服务位置,实现了服务消费者和服务生产者的高度解耦,SOA可以消除信息孤岛并实现共享业务重用。Mall4j商城系统则是使用了比起SOA还要灵活好用的微服务架构,微服务关注的是解耦,努力降低业务之间的耦合度,实现更多服务的复用,在DevOps有更大自由程度的持续交付。Mall4j商城系统的微服务技术包括Spring Cloud API网关、服务注册与发现、配置中心、负载均衡、分布式事务,其它相关技术包括有容器化技术、轻量级虚拟化、容器快速启停、易管理扩展、版本控制、应用安全隔离Mall4j商城系统应用使用范围电商系统B2C商城系统 【品牌电商】 单用户商城系统,统一后台管理、多终端覆盖B2B2C商城系统【平台电商】 多用户商城系统,自营+多商家入驻电商平台S2B2C商城系统【供应链】 融合供应链、为供应商、经销商、零售商赋能O2O商城系统【新零售】 线上线下融合,助力传统零食企业转型与发展应用终端电商平台【PC端、可视化】 可视化编辑,完善购物体验及商品数据分析商城小程序【小程序】 轻应用,体验优质,快速抢占移动电商市场商城APP【UNIAPP】 IOS、Android双APP,聚拢用户购物更便捷H5商城【HTML5】 手机浏览器,微信商城、随时随地五单支付。业务场景社交电商【移动电商】 融合拼团、会员分销等多种前沿社交营销模式积分商城【留存复购】 结合会员体系 、打造积分运营体系,引老留新跨境电商【海外】 海外支付,多语言切换,为企业提供跨境方案直播电商【引流获客】 微信小程序直播+电商模式,低成本变现流量Mall4j商城系统替换因素考虑Mall4j商城系统复杂,涉及的技术组件多,我们准备用OpenGauss替换MySQL5.7,改动的的东西涉及项目依赖文件、配置文件、解析文件,尤其数据库的内核能力以及对 应用框架的兼容 程度非常重要,假设开发者要大费周章大面积的改动,或者要动jar包的配置,估计OpenGauss替换MySQL5.7的计划就要搁浅或者放弃了。代码结构[root@enmoedu1 yami-b2b2c]# tree -L 1 . ├── CHANGELOG.md ├── compile.sh ├── db ├── doc ├── docker-compose.yml ├── LICENSE ├── log ├── mall4m ├── mall4uni ├── mall4v ├── pom.xml ├── README.md ├── screenshot ├── yami-shop-admin 商城后端接口服务管理系统,数据库操作有关 ├── yami-shop-api 商城前端接口调用系统,数据库操作有关 ├── yami-shop-bean ├── yami-shop-common pom.xml含有mysql的调用 ├── yami-shop-quartz ├── yami-shop-security ├── yami-shop-service └── yami-shop-sys src/main/resources/mapper/SysMenuMapper.xml 数据库操作有关 15 directories, 6 files pom.xml/opt/projects/yami-b2b2c/yami-shop-common目录, pom.xml内容如下,关于mysql的jdbc需要注释 改成 org.postgresql postgresql 42.2.2 logback-prod.xml/opt/projects/yami-b2b2c/yami-shop-admin/src/main/resources/logback/logback-prod.xml/opt/projects/yami-b2b2c/yami-shop-api/src/main/resources/logback/logback-prod.xml里面确定唯一的PROJECT_PATHapplication-dev.yml与 application-prod.ymldev是开发环境的配置参数 prod是生产环境的配置参数/opt/projects/yami-b2b2c/yami-shop-admin/src/main/resources/里面有两个文件application-dev.yml 和 application-prod.yml/opt/projects/yami-b2b2c/yami-shop-api/src/main/resources里面有两个文件application-dev.yml 和application-prod.yml把原来的注释,新的JDBC连接串如下 url: jdbc:postgresql://XXXXXX:15400/mytest username: henley password: XXXX driver-class-name: org.postgresql.Driver编译打包准备对代码进行编译打包,只需要在主代码下运行以下命令,这边主代码路径是/opt/projects/yami-b2b2c,当前目录下执行mvn clean package -DskipTests成功执行后如下所示自动在下面两处地方生成jar包,一个是商城后台接口,一个是商城前端接口/opt/projects/yami-b2b2c/yami-shop-admin/target/yami-shop-admin-0.0.1-SNAPSHOT .jar/opt/projects/yami-b2b2c/yami-shop-api/target/yami-shop-api-0.0.1-SNAPS HOT.jar开发调试 以开发的模式运行以下两个后端服务,可以获取DEBUG日志-Dspring.profiles.active=dev 意味着用开发模式运行 -Dspring.profiles.active=prod 意味着用生产模式运行以下命令启动后台服务,运行成功会发现8085端口打开nohup java -jar -Dspring.profiles.active=dev "/opt/projects/yami-b2b2c/yami-shop-admin/target/yami-shop-admin-0.0.1-SNAPSHOT.jar" > "/opt/projects/yami-b2b2c/yami-shop-admin/target/log/yami-shop-admin-console.log" &以下命令启动前端服务,运行成功会发现8086端口打开nohup java -jar -Dspring.profiles.active=dev "/opt/projects/yami-b2b2c/yami-shop-api/target/yami-shop-api-0.0.1-SNAPSHOT.jar" > "/opt/projects/yami-b2b2c/yami-shop-api/target/log/yami-shop-api-console.log" &查看控制台日志输出后台服务日志tail -f ${PROJECT_PATH}/log/admin.log前端服务日志tail -f ${PROJECT_PATH}/log/api.log启动后端服务管理平台进入 mall4v-master管理目录 [root@enmoedu1 mall4v-master]# npm run dev直接访问cid:link_0 ,它会直接与后台服务8085以及前端服务8086连线。数据库梳理ER图Mall4j一共有56个表示例MySQL表相关56个表都要做不同程度的修改,要修改替换的地方,举例MySQL表。CREATE TABLE `qrtz_job_details` ( `SCHED_NAME` varchar(120) unsigned NOT NULL AUTO_INCREMENT , `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL, `IS_NONCONCURRENT` varchar(1) NOT NULL, `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL, `JOB_DATA` blob, `JOB_tinyint` tinyint(2), `JOB_smallint` smallint(10), `JOB_int` int(10), `JOB_bigint` bigint(10), file_path varchar(255) DEFAULT NULL COMMENT '文件路径', file_type varchar(20) DEFAULT NULL COMMENT '文件类型', upload_time datetime DEFAULT NULL COMMENT '上传时间', `JOB_DATA_double` double(12,2), PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 数据类型数据类型的改造是一段工作量blob 改成 bytea tinyint(2) 改成 smallint smallint(10) 改成 smallint int(10) 改成 int bigint(10) 改成 bigint double(12,2) 改成 double precision datetime 改成 date数据索引openGauss的数据索引与MySQL的不一样 create index IDX_QRTZ_J_REQ_RECOVERY on qrtz_job_details (SCHED_NAME,REQUESTS_RECOVERY); create index IDX_QRTZ_J_GRP on qrtz_job_details(SCHED_NAME,JOB_GROUP);数据注释openGauss的数据注释与MySQL的不一样comment on column qrtz_job_details.file_path is '文件路径'; comment on column qrtz_job_details.file_type is '文件类型';自增ID表openGauss的自增ID与MySQL不一样 ,与主流的Postgresql的一模一样,它用自己的序列函数。GRANT ALL PRIVILEGES ON TABLE tz_sys_log TO henley; create sequence public.tz_sys_log_id start with 846 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.tz_sys_log_id owner to henley; alter table tz_sys_log alter column id set default nextval('public.tz_sys_log_id');UUID表tz_user表有user_id使用的是uuidopenGauss要支持uuid,可以通过FUNCTION,下面定义sys_guid的FUNCTIONmytest=# \sf sys_guid CREATE OR REPLACE FUNCTION pg_catalog.sys_guid() RETURNS character varying LANGUAGE sql NOT FENCED NOT SHIPPABLE AS $function$ select upper(md5(random()::text || clock_timestamp()::text)) $function$; mytest=# select sys_guid() ; sys_guid ---------------------------------- 72F965C6E7FC0F5D547787E969D5596F (1 row) mytest=# select sys_guid() ; sys_guid ---------------------------------- 3FBC1EC7357AC11BA0B06F4D116E051A (1 row) mybatis的SQL表达XML由于openGauss语法对符号 不识别,要把 的特殊符号都去掉 /opt/projects/yami-b2b2c/yami-shop-sys/src/main/resources/mapper/SysMenuMapper.xmlSysMenuMapper.xml 把 `` 的特殊符号都去掉。举例一个增加会员的涉及的数据库相关的修改操作现在在后台管理页面,点击管理员列表,再单击新增, 直接转发请求到后端服务yami-shop-admin,会触发数据库新增数据查看后端服务日志 tailf /opt/projects/yami-b2b2c/yami-shop-admin/target/log/yami-shop-admin-console.log### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: permission denied for relation tz_sys_user Detail: N/A ### The error may exist in com/yami/shop/sys/dao/SysUserMapper.java (best guess) ### The error may involve com.yami.shop.sys.dao.SysUserMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO tz_sys_user ( username, password, email, mobile, status, shop_id, create_time ) VALUES ( ?, ?, ?, ?, ?, ?, ? ) ### Cause: org.postgresql.util.PSQLException: ERROR: permission denied for relation tz_sys_user Detail: N/A ; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: permission denied for relation tz_sys_user Detail: N/A以上错误主要是由于没有授权,通过超管进入 mytest数据库openGauss=# \c mytest; Non-SSL connection (SSL connection is recommended when requiring high-security) You are now connected to database "mytest" as user "omm". mytest=# GRANT ALL PRIVILEGES ON TABLE tz_sys_user TO henley;继续查看yami-shop-admin-console.log,报错变成ERROR: null value Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint Detail: Failing row contains (null, 3, 1). at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2553) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2285) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:323) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401) at 以上报错ERROR: null value 原因是自增ID的问题,通过以下方法实现自增ID。create sequence public.tz_sys_user_id start with 2 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.tz_sys_user_id owner to henley; alter table tz_sys_user alter column user_id set default nextval('public.tz_sys_user_id'); **tz_sys_user 表与 tz_sys_user_role表、tz_sys_log表有关联,同样需要以下授权 **GRANT ALL PRIVILEGES ON TABLE tz_sys_user_role TO henley; create sequence public.tz_sys_user_role_id start with 1 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.tz_sys_user_role_id owner to henley; alter table tz_sys_user_role alter column id set default nextval('public.tz_sys_user_role_id');注意tz_sys_log表已经有845条数据,所以新增的数据从846开始算。GRANT ALL PRIVILEGES ON TABLE tz_sys_log TO henley; create sequence public.tz_sys_log_id start with 846 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.tz_sys_log_id owner to henley; alter table tz_sys_log alter column id set default nextval('public.tz_sys_log_id');创建用户成功后 mytest=# select * from tz_sys_log where id = 846;最后总结开源Mall4j商城系统的数据库底座替换,把MySQL改成OpenGauss,对业务逻辑相关的代码侵入不大,主要工作量是数据库表结构方面重构,OpenGauss对微服务的功能是支持的。
-
本文介绍如何快速安装OpenGauss3,OpenGauss3的安装这是笔者浓缩提炼的,并且在SpringBoot中集成使用OpenGauss3数据库。单机版openGauss3快速环境安装groupadd dbgroup useradd -g dbgroup omm # 可后面安装时创建 passwd omm #设置密码为Gauss_1234创建安装程序目标目录mkdir /home/omm/opengauss3 chown -R omm:dbgroup /home/omm/opengauss3下载opengauss3.00mkdir /opengauss3 cd /opengauss3 wget https://opengauss.obs.cn-south-1.myhuaweicloud.com/3.0.0/x86/openGauss-3.0.0-CentOS-64bit-all.tar.gz解压文件tar -zvxf openGauss-3.0.0-CentOS-64bit-all.tar.gz tar zxvf openGauss-3.0.0-CentOS-64bit-cm.tar.gz tar zxvf openGauss-3.0.0-CentOS-64bit-om.tar.gz设置opengauss集群配置文件,这里设单点安装[root@enmoedu1 opengauss3]# cat cluster_config.xml "/> 前置系统软件包yum install -y epel-release yum install -y bzip2 # 安装bzip2用于后面的解压openGauss安装包 sed -i 's/源IP/目标IP/g' cluster_config.xml sed -i 's/hdp1/你的主机名/g' cluster_config.xml 初始化系统安装配置参数,以必须管理员root的权限运行,进入opengauss3运行初始化程序[root@hdp1 ~]# cd /opengauss3/ [root@hdp1 opengauss3]# ./script/gs_preinstall -U omm -G dbgroup -X ./cluster_config.xml Parsing the configuration file. Successfully parsed the configuration file. Installing the tools on the local node. Successfully installed the tools on the local node. Setting host ip env Successfully set host ip env. Are you sure you want to create the user[omm] (yes/no)? no Preparing SSH service. Successfully prepared SSH service. Checking OS software. Successfully check os software. Checking OS version. Successfully checked OS version. Creating cluster's path. Successfully created cluster's path. Set and check OS parameter. Setting OS parameters. Successfully set OS parameters. Warning: Installation environment contains some warning messages. Please get more details by "/opengauss3/script/gs_checkos -i A -h hdp1 --detail". Set and check OS parameter completed. Preparing CRON service. Successfully prepared CRON service. Setting user environmental variables. Successfully set user environmental variables. Setting the dynamic link library. Successfully set the dynamic link library. Setting Core file Successfully set core path. Setting pssh path Successfully set pssh path. Setting Cgroup. Successfully set Cgroup. Set ARM Optimization. No need to set ARM Optimization. Fixing server package owner. Setting finish flag. Successfully set finish flag. Preinstallation succeeded.下面要以omm的用户正式运行安装程序,首先必须把权限赋给ommchown -R omm:dbgroup /opengauss3 切换到 omm,在/opengauss3目录下运行安装目录 [root@hdp1 opengauss3]# su omm [omm@hdp1 opengauss3]$ ./script/gs_install -X ./cluster_config.xml Parsing the configuration file. Check preinstall on every node. Successfully checked preinstall on every node. Creating the backup directory. Successfully created the backup directory. begin deploy.. Installing the cluster. begin prepare Install Cluster.. Checking the installation environment on all nodes. begin install Cluster.. Installing applications on all nodes. Successfully installed APP. begin init Instance.. encrypt cipher and rand files for database. Please enter password for database: Please repeat for database: begin to create CA cert files The sslcert will be generated in /home/omm/opengauss3/install/app/share/sslcert/om NO cm_server instance, no need to create CA for CM. Cluster installation is completed. Configuring. Deleting instances from all nodes. Successfully deleted instances from all nodes. Checking node configuration on all nodes. Initializing instances on all nodes. Updating instance configuration on all nodes. Check consistence of memCheck and coresCheck on database nodes. Configuring pg_hba on all nodes. Configuration is completed. Successfully started cluster. Successfully installed application. end deploy..验证服务进程是否激 活[root@hdp1 ~]# ps -eaf | grep omm root 14898 32160 0 15:55 pts/1 00:00:00 su omm omm 14899 14898 0 15:55 pts/1 00:00:00 bash omm 19411 1 9 16:08 ? 00:00:02 /home/omm/opengauss3/install/app/bin/gaussdb -D /home/omm/opengauss3/install/data/dn root 19784 360 0 16:09 pts/2 00:00:00 grep --color=auto omm命令行登录gsql -d postgres -p 15400 安装opengauss3注意事项之前安装mogdb,影响了opengauss3的环境,/home/omm/.bashrc 里面记录了安装后的变量,如果要卸载opengauss,必须要把.bashrc 下面所有的东西都去掉。# User specific aliases and functions export GPHOME=/home/omm/opengauss3/install/om export PATH=$GPHOME/script/gspylib/pssh/bin:$GPHOME/script:$PATH export LD_LIBRARY_PATH=$GPHOME/lib:$LD_LIBRARY_PATH export PYTHONPATH=$GPHOME/lib export GAUSSHOME=/home/omm/opengauss3/install/app export PATH=$GAUSSHOME/bin:$PATH export LD_LIBRARY_PATH=$GAUSSHOME/lib:$LD_LIBRARY_PATH export S3_CLIENT_CRT_FILE=$GAUSSHOME/lib/client.crt export GAUSS_VERSION=3.0.0 export PGHOST=/home/omm/opengauss3/tmp export GAUSSLOG=/var/log/omm/omm umask 077 export GAUSS_ENV=2 export GS_CLUSTER_NAME=dbClusterspringBoot应用集成OpenGaussSOA是一种粗粒度、松耦合服务架构,服务之间通过简单、精确定义接口进行通讯,不涉及底层编程接口和通讯模型。SOA可以看作是B/S模型、XML(标准通用标记语言的子集)/Web Service技术之后的自然延伸,面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的人为依赖性。简而言之SOA可以消除信息孤岛并实现共享业务重用,我们通过SOA可以打造下图的复杂系统,其中蓝色用户服务 ,我们可以通过springboot + OpenGauss 技术实现。我们使用OpenGauss作为具体数据存储,使用开发工具创建一个数据库mysqltest,并在mysqltest数据库中创建一张表userennity和user1,创建语句如下:create table userentity( id int , username varchar(50), password varchar(50), user_sex varchar(10), nick_name varchar(50) ); create table user1( id int , name varchar(50), password varchar(50)); DEMO代码 +---src | +---main | | +---java | | | ---com | | | ---main | | | +---controler 具体业务逻辑 | | | +---mapper 定义实现DAO的CRUD实体操作 | | | +---model 实体类 | | | ---service 实现服务类注意UserControler是首先调用的service,继而去调用实体操作。 而UserEntityControler是通过mapper的封装去调用 DAO的CRUD的操作,如下无论是UserControler还是 UserEntityControler 都需要底层数据库对应用支持友好。 确定opengauss的用户、密码、端口及相关IP启动服务服务正在运行中 查看用户实体1查看用户实体2源代码下载:链接:cid:link_0 提取码:5wjdspringboot集成opengauss的FAQ用户名/密码不对spring报错### The error may involve com.main.mapper.UserMapper.getAll ### The error occurred while executing a query ### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is org.postgresql.util.PSQLException: 不明的原因导致驱动程序造成失败,请回报这个例外。] with root cause java.lang.NullPointerException: null而opengauss内部执行报错[omm@enmoedu1 ~]$ gsql -U henley -h 192.168.30.65 -p 15400 Password for user henley: gsql: FATAL: Invalid username/password,login denied.根本原因分析 openGauss默认是sha256,而登录则设成只允许md5登录,所以一直识用户名和密码错误解决方法及步骤 vi /home/omm/opengauss3/install/data/dn/postgresql.conf 修改设置 encryption_type = 1vi /home/omm/opengauss3/install/data/dn/pg_hba.conf增加设置 host all henley 0.0.0.0/0 md5用户没有对表的操作权限spring报错org.postgresql.util.PSQLException: ERROR: permission denied for relation userentity 详细:N/Aopengauss报错mytest=> SELECT id, userName, passWord, user_sex, nick_name FROM userentity; ERROR: permission denied for relation userentity DETAIL: N/A解决方法及步骤以postgres的身份登录root[omm@enmoedu1 ~]$ gsql -d postgres -p 15400 gsql ((openGauss 3.0.0 build 02c14696) compiled at 2022-04-01 18:12:34 commit 0 last mr ) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help.切换到指定的数据库openGauss=# \c mytest; Non-SSL connection (SSL connection is recommended when requiring high-security) You are now connected to database "mytest" as user "omm".执行授权mytest=# GRANT ALL PRIVILEGES ON userentity TO henley; GRANT授权后能够正常,但是发现一个问题,现在我们是通过Postgresql的jdbc驱动去访问OpenGauss的,OpenGauss没有自己的原生jdbc驱动吗?答案是有的,而且还支持maven方式,见下。 但是笔者的运气很差,通过maven一直无法下载openGauss的core包,只能通过手动的方式下载。wget https://opengauss.obs.cn-south-1.myhuaweicloud.com/ 3.0.0/x86/openGauss-3.0.0-JDBC.tar.gz再在idea把jar包引入进来,引入步骤 Project Structure --> Project Settings --> Libraries --> Add(alt +insert) --> applyapplication.properties稍微修改一下 ==spring.datasource.url=jdbc:opengauss://192.168.30.65:15400/mytest== ==spring.datasource.driver-class-name=org.opengauss.Driver==#spring.datasource.url=jdbc:postgresql://XXXX:5432/mytest #spring.datasource.url=jdbc:postgresql://XXXX:15400/mytest spring.datasource.url=jdbc:opengauss://XXXX:15400/mytest spring.datasource.username=henley spring.datasource.password=XXXX spring.datasource.driver-class-name=org.opengauss.Driver #spring.datasource.driver-class-name=org.postgresql.Driver ### mybatis config ### mybatis.config-locations=classpath:mybatis/mybatis-config.xml mybatis.mapper-locations=classpath:mybatis/mapper/*.xml mybatis.type-aliases-package=com.main.model最后总结openGauss对业界知名的spring支持还算友好,直接用传统的postgresql驱动就可以接入使用,也有自己的opengauss驱动。如果使用顺利,还可以支持分布式配置、服务路由、负载均衡、熔断限流、链路监控这些功能,事实上在微服务的技术框架上也是支持的。
summersummer007
发表于2022-10-09 17:29:39
2022-10-09 17:29:39
最后回复
summersummer007
2022-10-09 17:29:40
296 0 -
SSM介绍SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容),常作为数据源较简单的web项目的框架。SpringSpring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。 Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new一个对象,而是让Spring框架帮你来完成这一切。SpringMVCSpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。mybatismybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。 页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。SSM搭配的数据库无庸置疑,SSM经常搭配的数据库是MySQL或者是Postgresql,而国内使用MySQL的人比 Postgresql的人多, 所以本文主要内容关于SSM DEMO已经搭配用上MySQL,系统本身可以注册写入数据入库,可以从库中读取数据进行登录。SSM demo代码经过测试对比,SSM DEMO代码基于三个不同的数据库,除了JDBC连接串不同,如下。另外最大的不同就是数据库的ID自增机制不同,ID自增机制是数据库的一项基本功能,我们非常重视这一点,这个不同会不会导致DEMO代码要做相关的适配,好听叫做适配,不好听叫做业务侵入。我们现在开发的 SSM DEMO代码是在MySQL的基础上开发,优先满足了MySQL。Postgresql如果把MySQL改换成Postgresql ,运行程序的会报错,如下org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: ### Error updating database. Cause: org.postgresql.util.PSQLException: Returning autogenerated keys is only supported for 8.2 and later servers. ### SQL: insert into user1 (username, password, age) values (?, ?, ?) ### Cause: org.postgresql.util.PSQLException: Returning autogenerated keys is only supported for 8.2 and later servers.笔者用的是postgresql12,经过网上查阅 ,mybatis的定义配置必须要更改。 ==useGeneratedKeys="true" keyProperty="id"摘掉==改换成 重新在idea运行tomcat9如下,发现数据能够写入了,但是写入的数据没有id列为空值。mytest=# select * from user1; id | username | password | age ----+-----------+-----------+----- 1 | user1 | password1 | 18 | hexin.xue | cxc | 25这是由于postgresql没有自动增加id机制的功能,所以数值一直为空。 如果要实现自增ID,它是通过sequence去实现增加ID的。两个方法是给相关表增加sequence,一种是已建表的基础上增加sequence实现增加IDcreate sequence public.userid_seq start with 1 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.userid_seq owner to henley; alter table user1 alter column id set default nextval('public.userid_seq'); insert into user1 (username, password, age) values ('username1', 'password1', 100);另外一种重建表,建表就实现CREATE SEQUENCE sq_user_id START 1 INCREMENT 1 CACHE 20; create table user1(id int NOT NULL DEFAULT nextval('sq_user_id') , username varchar(50),password varchar(50),age int);建表后如果还有问题 ,下面再补刀alter sequence public.sq_user_id owner to henley; alter table user1 alter column id set default nextval('public.sq_user_id');增加sequence后,写入数据后ID例有值了。OpenGauss依然是同样代码,把jdbc的连接串改成OpenGauss, 我们启动tomcat,加载服务,我们惊喜的发现没有报错。 此处在postgresql12需要更改,在opengauss3不需要任何更改,spring指向的应用层没有报错。但是数据库底层ID列的数据仍然空值,OpenGauss也和Postgresql一样,都是用sequence 去实现ID的自增长。create sequence public.userid_seq start with 1 increment by 1 no minvalue no maxvalue cache 1; alter sequence public.userid_seq owner to henley; alter table user1 alter column id set default nextval('public.userid_seq');**体验源代码: **链接:cid:link_0 提取码:0kwg最后总结这是SSM开发中比较低端的DEMO代码,但是从中可见openGauss用心的包容,在接口层适配了mybatis,遇到自增ID提高了容错性,相对于postgresql多了一道方便。
summersummer007
发表于2022-10-09 17:15:57
2022-10-09 17:15:57
最后回复
summersummer007
2022-10-09 17:15:57
12 0 -
1 前言openGauss是一款全面友好开放的企业级开源关系型数据库。openGauss采用木兰宽松许可证v2发行,提供面向多核架构的极致性能、全链路的业务、数据安全、基于AI的调优和高效运维的能力。本文采用openGauss设计一个AI小demo。2 方案意义人工智能被广泛用于棋类对弈的主要原因是:棋类对弈自古以来就被认为是人类智力活动的象征,若人工智能成功达到、甚至高于人类水平,则就代表AI的发展潜力,从而吸引更多研究者关注并投身其中; 棋类很适合作为新AI算法的标杆。棋类游戏规则简洁、输赢都在盘面,适合计算机求解。理论上只要在计算能力和算法上有新的突破,任何新的棋类游戏都有可能得到攻克。而在棋类游戏上的表现也可以直观体现出AI之间计算能力与算法的高低,是促进AI算法发展的有效途径。 就本五子棋智能对弈系统而言,其服务对象为同局域网下的多个终端,讲求联机互动、互相限制、互相博弈,打破了传统二人对弈五子棋规则中,“若无禁手,先手易胜;若为后手,十堵九输”的说法,是AI算法设计、网络通信、数据库等技术的综合应用。3 架构设计其中对弈数据库采用openGauss数据库4 数据表设计棋盘数据表的表头如图所示为将二维棋盘状态存入数据库中,令棋盘按 轴方向展开为一维序列玩家数据表的表头如图所示走子数据表的表头如图所示5 代码结构如图所示,依据模块化程序设计的基本思想,将整个项目按照功能划分为若干个小程序模块,每个小程序模块完成一个确定的功能,自顶向下、逐步分解、分而治之,各模块相对独立、功能单一、结构清晰。同时,在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计各模块具体设计如下:main.py:启动文件。config.py:变量管理文件。管理所有跨文件的全局变量。settings.py:配置文件。开发环境配置、第三方扩展插件参数配置、数据库的链接路径及其他配置等。apps:主体文件包。其初始化文件包括Flask类的实例创建以及工厂函数。该文件包下设三个子文件包,分别对应架构设计中的三张蓝图。exts:扩展文件包。第三方扩展插件的例化,创建映射对象等。 项目采用高度模块化设计的优点有:控制了程序设计的复杂性;提高了代码的重用性;易于维护和功能扩充;有利于团队开发等。6 项目演示7 总结基于openguass开发AI应用相当方便,也使我进一步掌握了数据库的常用技术,提高工程开发能力和面对未知问题的临场解决能力,对设计、创新、分析水平都有很大的帮助
summersummer007
发表于2022-10-09 15:59:46
2022-10-09 15:59:46
最后回复
summersummer007
2022-10-09 15:59:46
36 0 -
数据库的优化器相当于人类的大脑,大部分时候都能做出正确的决策,制定正确的执行计划,走出一条高效的路,但是它毕竟是基于某些固定的规则、算法来做的判断,有时候并没有我们人脑思维灵活,当我们确定优化器选择执行计划错误时该怎么办呢,语句上加hint,提示它选择哪条路是一种常见的优化方法。前言数据库的优化器相当于人类的大脑,大部分时候都能做出正确的决策,制定正确的执行计划,走出一条高效的路,但是它毕竟是基于某些固定的规则、算法来做的判断,有时候并没有我们人脑思维灵活,当我们确定优化器选择执行计划错误时该怎么办呢,语句上加hint,提示它选择哪条路是一种常见的优化方法。我们知道Oracle提供了比较灵活的hint提示来指示优化器在多表连接时选择哪种表连接方式,比如use_nl,no_use_nl控制是否使用Nest Loop Join,use_hash,no_use_hash控制是否使用hash join。但是MySQL长期以来只有一种表连接方式,那就是Nest Loop Join,直到MySQL8.0.18版本才出现了hash join, 所以MySQL在控制表连接方式上没有提供那么多丰富的hint给我们使用,hash_join与no_hash_join的hint只是惊鸿一瞥,只在8.0.18版本存在,8.0.19及后面的版本又将这个hint给废弃了,那如果我们想让两个表做hash join该怎么办呢?实验我们来以MySQL8.0.25的单机环境做一个实验。建两个表,分别插入10000行数据,使用主键做这两个表的关联查询。create table t1(id int primary key,c1 int,c2 int);create table t2(id int primary key,c1 int,c2 int);delimiter //CREATE PROCEDURE p_test()BEGINdeclare i int;set i=1;while i<10001 doinsert into t1 values(i,i,i);insert into t2 values(i,i,i);SET i = i + 1;end while;END;//delimiter ;查询一下两表使用主键字段关联查询时实际的执行计划,如下图所示:查询一下两表使用非索引字段关联查询时实际的执行计划,如下图所示:从执行计划可以看出,被驱动表的关联字段上有索引,优化器在选择表连接方式时会倾向于选择Nest Loop Join,当没有可用索引时倾向于选择hash join。基于这一点那我们可以使用no_index提示来禁止语句使用关联字段的索引。从上面的执行计划可以看出使用no_index提示后,优化器选择了使用hash join。当索引的选择性不好时,优化器选择使用索引做Nest Loop Join是效率是很低的。我们将实验的两个表中c1列的数据做一下更改,使其选择性变差,并在c1列上建普通索引。update t1 set c1=1 where id<5000;update t2 set c1=1 where id<5000;create index idx_t1 on t1(c1);create index idx_t2 on t2(c1);当我们执行sql :select t1.*,t2.* from t1 join t2 on t1.c1=t2.c1;这个查询结果会返回大量数据,被驱动表的关联字段c1列的索引选择性差,此时选择hash join是更明智的选择,但是优化器会选择走Nest Loop Join。我们可以通过实验验证一下hash join 与 Nest Loop Join的性能差异。可以看出使用hash join的耗时是使用Nest Loop Join的1/6,但是优化器根据成本估算时,使用Nest Loop Join的成本要比使用hash join的成本低很多,所以会去选择Nest Loop Join,这个时候就需要加上hint 提示禁止使用关联字段的索引,被驱动表上每次都全表扫描的代价是很高的,这样优化器估算后就会选择走hash join。MySQL官方文档里提到用BNL,NO_BNL的hint提示来影响hash join的优化,但是经过实验证明,在表连接关联字段上没有可用索引时,优化器估算成本后不会对被驱动表使用BNL全表扫描的方式做嵌套循环连接,而是会选择使用hash join,那这样NO_BNL在这个场景下就没有用武之地了。那么既然不用这个索引,把这个索引去掉不就可以了吗?为什么非要使用no_index的hint提示呢,我们要知道业务使用的场景何其多,此处不用,别处使用了这个索引效率可能会有大的提升啊,这个时候就凸显了hint的优势,只需要控制此语句的使用就好了。总结Nest Loop Join有其优势,它是response最快的连接方式,适用于返回数据量小的场景。当两个大表连接,返回大量数据,且关联字段的索引比较低效时,使用hash join就会比较高效,我们可以使用no_index的hint提示禁用关联字段的低效索引,促使优化器选择hash join。来源: GreatSQL社区
-
近期,由国家工业信息安全发展研究中心发布了2022年《分布式数据库发展趋势研究报告》。报告从数据库产业发展、分布式数据库产品价值、面临调整、技术路线、发展趋势、发展方向等多角度阐述了分布式数据库的诸多问题。本文,从个人角度谈谈对上述研究报告的解读。1、背景篇:不鸣则已、一鸣惊人伴随着数字化转型深化,企业对于数据的重视程度逐步加深。伴随着以云计算、5G、IOT、人工智能、区块链等新兴技术的发展,催着更多新兴数据场景的出现。这其中直观带来的就是数据规模呈现几何级增长、数据结构复杂度与日攀升。根据第三方机构的预测数据,全球数据存储量在未来几年将呈现爆炸式增长。除去数据规模外,在从数据采集、存储、传输、展现、分析和优化等方面都对数据的载体数据库提出了更高的要求。希望以此更好地实现企业对数据资产治理、增值与科学决策,数据高可靠高可用、数据在线分析等诉求,进一步发挥数据价值。上述诉求可以说为数据库提出了更高的要求,但传统数据库架构在超大规模、高并发、实时处理、数据安全等方面明显力不从心,此外高昂建设成本也难以迎合数字化时代的潮流趋势。相较于传统数据库,新兴分布式数据库的优势都凸显出来。突破规模化存储能力传统单机或集中式架构下,承载的数据规模受限于本地磁盘或可对接的外部存储空间。虽然后者可做到大规模(如PB级),但其建设周期长、扩展不灵活、投入成本高且依然还会面临IO的性能瓶颈。而分布式架构数据库,天然具有的数据分片能力,是有效解决超大规模数据承载的利器。突破高性能计算瓶颈作为承载计算的主要资源,CPU、内存资源对计算尤为重要。在传统单机或集中式架构下,上述资源仅能通过Scale UP方式进行扩展,其扩展能力有限,无法整合更多资源参与计算。而分布式架构数据库,通过网络可汇聚更多计算资源参与其中,形成更大规模的算力支持。在高并发、高性能计算领域更有优势。填补数据分析能力短板数据分析,是数据使用的重要方向之一,过去通常是由数据仓库等技术承载。这种在线数据库与离线数据仓库的架构,能在一定程度上解决数据分析问题,但在实时性、一致性、成本等方面存在短板。理想的方式在单一系统完成,但传统架构受限于资源,无法完全提供。而分布式架构数据库,通过其算力的整合可满足混合负载的业务压力,大幅度提升分析时效性,并减少数据冗余,灵活性大大提高。提升可用性与安全性传统架构下,数据库可用性更多取决于单点(或存储),设计上往往通过冗余硬件保护等方式去提升;但受限于架构约束难以达到非常高的可用性。针对数据安全,也通常是通过主备复制、备份等手段完成,但难以保证数据在线安全,需要窗口期完成恢复。分布式架构具备的存算分离、多副本、弹性扩展等能力,可有效提升整体可用性和数据安全。用户可根据需要,灵活调整架构,提升可用性和安全性。优化成本模型实现按需扩展传统架构数据库的成本相对高昂,这主要是由于其架构限制,向上扩展相对容易,水平扩展比较困难。为了保证快速的业务发展,通常在项目设计初期就需要按最大容量进行规划或为了更高的可靠性需要付出高额的成本。而分布式架构数据库则不同,其架构天然就支持灵活扩展能力(包括存储、计算),并可实现低成本的高可用解决方案(多副本)。上述能力,将有效降低企业在构建系统时的投入,特别是在面对快速、多变业务的场景更是如此。2、技术篇:百花齐放、百家争鸣从上图可见,分布式数据库已经发展多年,特别是近些年来已经逐步成熟并落地使用。从大的技术路线来看,可大致分为几种类型:路线:分布式中间件+单机数据库这一技术路线是在单机数据库系统上进行改造,主要解决计算存储的扩展性问题。上层为一组无状态计算节点,基于分片规则提供SQL解析,请求转发和结果合并的能力。下层为增强的单机数据库,提供单机数据库的存储和执行能力。这一架构通过数据在逻辑层的切割,可近似线性地对计算性能和存储容量进行扩展,具有可规模化扩展的能力。路线:分布式存储构建这一技术路线是通过构建分布式共享存储实现扩展,采用非对称计算节点,大部分公有云数据库是这条路线。这条路线有限地解决扩展性问题,跨地域数据一致性主要依赖分布式存储引擎。共享存储能够跨多个节点提供读写,上层的计算部分是无状态的一组节点组成。当有写能力的计算节点出现故障时,会自动从可用的读节点中自动选出一个作为写节点,实现写能力的高可用。路线:原生分布式这一技术路线是原生分布式数据库,各计算节点提供对等的读写服务。这条路线是根据分布式一致性协议做底层设计,与传统数据库有本质区别。原生分布式数据库将分布式存储、事务、计算有机的结合在一起,数据由系统自动打散并存储多个副本,通过一致性协议保证多个副本和事务日志的一致性,对分布式事务、全局MVCC等支持更为彻底。整个分布式结构是包裹在集群内部的,应用对此无感知。3、 趋势篇:石以砥焉、化钝为利随着分布式架构数据库在众多场景使用,再享受到其带来的收益之外,也对这一新架构产品提出了更多的挑战。这些挑战也为未来分布式数据库发展指明了方向。(1)融合化原生设计如上面谈到的分布式数据库存在不同路线,不同路线产品差异明显。从长期发展来看,不同路线产品呈现逐步融合的现象,各家各取所长,不断丰富产品能力。一方面相较于单机或集中式架构,分布式架构产品仍然存在诸多短板,可理解为基础能力补齐;另一方面用户对于分布式能力也提出了更高的要求,可理解为扩展能力增强。基础能力补齐在分布式架构下,相较于单机或集中式架构,仍存在大量短板问题。这些会直接影响到用户的使用体验。如分布式事务的一致性保证问题,对于单机较容易实现的ACID,分布式环境中出现了更多的难题。分布式数据库将需要处理的事务进行拆分,再部署到不同的服务器上进行处理,理想状况下,整个过程需要全局一致性协议的保护,而分库分表两阶段的方式在一些意外情况下容易出现问题。再比如,分布式架构多采用存算分离架构,其天然会带来分层间网络开销问题,如何解决低延迟需求值得考虑。扩展能力增强随着分布式数据库的使用,如何使用好这一架构成为核心。例如在分布式场景下,如何做好数据分片的智能化。分布式通过分库分表进行数据拆分,从而各表的数据量保持在阈值以下,从而应对高并发和海量数据,但如何高效的、高质量的进行分片,还需再探索。此外,作为以一种新架构产品,分布式数据库所具备的弹性扩缩容、按需扩展、海量支持、多副本细粒度控制等课题,都是值得深入挖掘。(2)负载一体化设计企业级应用的业务场景通常可以分为联机交易和实时分析两种,通常称为OLTP和OLAP的业务应用。由于是不同的应用场景,很多企业往往会选择多款数据库产品分别支持。这种组合式的解决方案要求数据在不同产品间进行流转,数据的同步过程就带来了时间延迟和数据不一致的风险,而且还会产生冗余数据,成本开销被迫提高,这在一定程度上限制了企业的发展。分布式数据库的出现,为企业解决上述问题带来了契机,这也是近年来HTAP(混合负载)的兴起,其旨在打破事务处理和分析之间“壁垒”。未来分布式数据库都应具备混合负载能力,即在支持高并发、事务性请求的同时,也对分析型的复杂查询提供了良好的支持,实现计算、I/O资源互不干扰。通过在线交易和分析互不影响,一站式地解决企业级应用的各种需求,从而大幅度降低成本,同时提高了企业决策的效率。(3)云与云原生设计根据全球知名咨询公司Gartner指出,“到2022年,75%的数据库将被部署或迁移到云平台…”云化无疑代表了未来。数据库作为IT基础设施,如何与云环境融合成为大家的问题。特别是分布式数据库,其架构需要大量资源构建。如何通过与云的结合,有效解决灵活部署、弹性扩缩容、资源管理乃至如何更好地利用云基础资源做到真正的云原生,这些都是分布式数据库需要考虑的。因此在分布式数据库产品设计层面就要充分适配云环境、兼容更多云技术,从而添加更多资源管控、多部署形态、云原生资源利用等云化方面的能力。(4)高可用一致性设计作为数据库的基本能力要求,服务高可用和数据一致性一直是企业选择数据库的重点考察要求。特别是随着数字化转型,更多数据参与到企业业务流转中,这些都对如可用性提出更好要求。传统数据库架构,在满足7×24小时的服务不中断和数据零丢失方面往往已经超出其可承受能力,或者即使能解决其成本也十分高昂。分布式数据库具备的分层、多组件、多节点架构成为解决高可用的基础,有效控制故障范围、主动发现自愈等手段可大幅提升服务可用性。同时,其多副本机制为数据一致性安全提供可能,这也是相较于传统架构的突破,可做到数据更为精细粒度的一致性,满足各种数据场景下对一致性的不同等级要求。(5)软硬结合异构设计硬件和软件是信息系统的核心组件,两者之间相辅相成,互相促进。新型硬件的出现,可以为数据库发展带来更多的收益。一方面以基础硬件如多核CPU、异构计算(如GPU、FPGA)持久化内存、高速网络为代表的硬件出现,为分布式数据库架构提供更多的想象空间;另一方面新型硬件也会为数据库设计带来更多挑战,如何利用好新硬件值得各数据库厂商思考,甚至会颠覆之前的设计模式。此外,作为关键基础设施,数据库还要为操作系统、芯片的灰度替换提供支持,而在关键行业及软件领域,数据库还需要提供对异构芯片的支持,从而提升数字化解决方案的严谨性,降低应用风险。(6)全密态安全设计当前信息安全已经上升到国家战略高度,诸多行业监管机构和政府部门对数据存储和使用都有明确的安全合规性要求。2021年11月公布的《中华人民共和国个人信息保护法》,监管部门已在金融等行业中推广数据加密,要求敏感数据采用加密的方式进行存储。而作为数据承载主体的数据库,有义务为此提供坚实的数据安全保障。那么在分布式数据库设计之初,就需考虑在数据传输、数据存储、数据计算等多方面的安全问题。诸如透明数据加密、透明数据传输、多密钥管理、国密算法支持、密态计算等方面,都需要考虑。(7)低成本集约化设计分布式数据库,作为一种新架构产品,对于企业来说会带来不小成本。从管理角度来看,分布式架构对运维人员都带来新的要求,如何管理好成为要点。产品是否提供完整的管理能力、是否提供完备的生态工具等,将直接影响最终使用成果。从资源角度来看,分布式架构需要一定资源投入,如何规划设计好并通过诸如租户能力有效降低使用成本很重要。(8)高兼容易迁移设计对于底层数据库替换,最为头疼的就是数据库的替换。大部分企业经过企业信息化的长期积累与革新,在内部积累了大量的业务系统。传统的企业级数据库产品提供了强大的能力,协助开发者快速便捷地构建应用程序,但同时也导致应用设计过度依赖数据库功能。适配新的数据库产品必须对应用代码进行大量修改。没有两个数据库是完全一样的,分布式数据库更是如此。其在底层架构、实现逻辑上必然存在差异。比较好的方式,就是提供高兼容能力,这将有利于大幅降低代码改造成本。目前大多数分布式数据库还不完全具备主流数据库生态的兼容能力,兼容的种类还不够丰富,兼容度还有待提高。此外,分布式架构对于设计上也有着特殊的要求,如何降低研发设计成本,近似透明地屏蔽这一差异很重要。此外,数据从传统集中式数据库迁移至分布式数据库是一项复杂且庞大的工程。从前期兼容评估、应用设计改造,到中期的业务测试、性能测试,指导最终迁移完成并保证迁移准确性等,这些都需要提供全流程的支持。这也是目前分布式产品普遍有所缺失的。希望未来分布式数据库产品将具备全方位、高标准、高可靠性的平滑迁移能力。4、发展篇:知之非艰、行之惟艰分布式数据库作为新技术架构,如何推进是需要多方位的支持。从近些年来看,从国家、行业、用户等多方位都给予大力支持。从政策层面,将在作为数据基础设施之一的数据库提升到一定高度,重点布局针对数据库分布式转型、应用创新战略。在行业方面,越来越多的数据库厂商加入进来,特别是以分布式为特征的产品已然成为主流。在用户方面,以金融、电信为代表的高数据价值企业,已经开始在核心生产系统逐步使用。但同时我们也看到,分布式数据库在推进中,仍然存在诸多不足之处,这也是未来需重点关注发展之处。(1)培育自有生态数据库要想用好,是需要从“产、学、研、用”多角度考虑,是需要跟上下游生态形成合力,才能为客户提供更为完整的服务。相较于之前国外商业数据库或开源产品,国内数据库生态还需要加大投入,培育自有生态。在这其中,可以通过生态兼容加速这一过程,如何有效利用之前成熟生态值得考虑。此外,开源作为一种有效的生态构建手段,也是生态化建设的利器。(2)共建行业标准作为一种新型数据库,分布式架构尚未形成统一的行业标准或者事实标准。从最终用户角度来看,不得不面对纷繁复杂的产品细节,这也阻碍了分布式数据库的大范围推广。从行业整体发展角度来看,一方面可通过行业指导单位牵头,由行业内众多企业参与形成标准规范;一方面可通过构建标准化评测体系,建立可衡量标准。希望通过标准的建立,能探索出特色发展路径,抓住机遇尽早实现分布式数据库领域的换道超车。(3)树立专有评测分布式数据库,作为新产品有其架构特色。对于这一新产品的理解,各家各有不同。行业内急需统一的评测标准,从多维度评估这一新类型产品。这其中既包括传统数据库的基本能力,也需要包含分布式自有特点,如在高可用、备份恢复等。逐步建立其以功能测试、非功能测试及场景化测试相结合,形成完备的评测体系。(4)填补最后路径企业更换底层数据库,是一个颇为痛苦的过程,更换为一种全新架构产品更是如此。大量用户使用分布式架构的担忧是来自于对新架构、新产品的未知及对实施路径的陌生。前者我们可通过专有评测标准逐步熟悉,后者则需要通过最后路径的填补做好“最后一公里”。从选型评估、工作量评估、结构数据迁移、流量切换、上线保障等多角度,形成标准的实施路径将大大加速这一过程。写在最后:分布式数据库,尚处于发展早期,但已呈现蓬勃之势。虽然仍有很多不足,但发展空间巨大。这里送给分布式数据库从业者一句话:道阻且长,行则将至;行而不辍,未来可期!作者介绍韩锋,51CTO社区编辑,CCIA(中国计算机协会)常务理事,前Oracle ACE,腾讯TVP,阿里云MVP,dbaplus等多家社群创始人或专家团成员。有着丰富的一线数据库架构、软件研发、产品设计、团队管理经验。曾担任多家公司首席DBA、数据库架构师等职。在云、电商、金融、互联网等行业均有涉猎,精通多种关系型数据库,对NoSQL及大数据相关技术也有涉足,实践经验丰富。曾著有数据库相关著作《SQL优化最佳实践》、《数据库高效优化》。来源:51CTO博客
-
亲爱的伙伴们,Gauss松鼠会联合openGauss社区、鲲鹏社区、墨天轮共同共同举办【我和openGauss的故事】第四届openGauss技术文章征集活动踏秋而来~各位爱技术、爱思考、爱总结的小伙伴,你们施展才华的舞台已经搭建好~期待你的投稿作品!参与方式投稿:9月10日至10月15日,完成下面2步即投稿完成。在墨天轮社区或openGauss社区提交技术文章,并将链接发给Gauss松鼠会小助手(Gauss_Asst666)二维码:墨天轮社区:(cid:link_0),提交时需带有opengauss的标签。openGauss社区:https://opengauss.org 在墨天轮社区“我和openGauss的故事”有奖征文活动,将您发布的文章标题及链接复制黏贴到本活动宣传贴的评论区。参与评优:初审合格的文章将会同步发布在鲲鹏论坛-Database专区,我们会根据墨天轮社区&鲲鹏论坛的总点赞量进行片名,请关注文章的点赞量。活动推广:您还可以推荐好友参与投稿,每邀请2位好友完成openGauss社区投稿,可以获得“活动推广奖”。活动日程活动规则1、投稿:内容要求为openGauss相关技术文章,包含但不限于以下内容:系统技术解析、案例分享、实践总结、开发心得、客户案例、故障调试、测试比对、使用技巧、学习笔记等。文章要求原创且在墨天轮社区或openGauss社区首发,并且在墨天轮社区发布时需要加“openGauss”标签,在openGauss社区发布时需要加“openGauss技术文章征集”标签。若投稿文章为复制或抄袭他人文章,均视为无效。每篇文章要求不少于500字(可含代码),图文并茂,排版工整。2、初审:作者在投稿后,专家组将进行初审,通过初审的文章将参与评优活动;未通过初审的文章,专家组将给出修改建议,修改后可再次提交报名。3、评优通过初审的文章,将发布在鲲鹏论坛-DataBase专区,按墨天轮社区、鲲鹏论坛社区点赞的总赞数进行排名并给予奖励。奖品设置墨天轮投稿奖:根据文章价值和借鉴意义给与50~100元的激励。openGauss社区投稿奖:凡是在openGauss社区blog仓投稿并成功合入的,可以获得京东购物卡50/Gauss松鼠会保温杯/筋膜枪。活动推广奖:(20个)每邀请2位好友参与活动,完成openGauss社区投稿,即可获得一份“活动推广奖”,多邀多得,数量有限,先到先得。优秀奖:通过初审的文章,将发布在鲲鹏论坛-DataBase专区,按墨天轮社区、鲲鹏论坛社区点赞的总赞数进行排名并给予奖励。其他奖项:在墨天轮社区发布的文章,同时还可以参加墨力计划,详细内容请参见:cid:link_2注:如参与者投稿多篇作品,仅按文章最好成绩参与优秀奖排名。墨天轮投稿奖,openGauss社区投稿奖,活动推广奖,优秀奖相互独立,每位参与活动者获奖可叠加。openGauss社区投稿奖、推广奖和优秀奖获奖者需在鲲鹏社区完成实名认证后方可领取奖品。优秀奖得主需在openGauss社区同步发布获奖文章后方可领取奖品。奖品种类数量有限,先到先得。奖励发放墨天轮投稿奖每满20篇,将在墨天轮编辑部账号上及时公布获奖名单,大家请多多关注!中奖用户可以联络墨天轮小助手(微信:modb666)领取墨天轮投稿奖。openGauss社区投稿奖、推广奖与优秀奖将于10月16日整理后发布,届时请联络Gauss松鼠会小助手领取。
-
快速列表简介 在Redis3 .2版本之前,存储列表(list)数据结构使用的是压缩列表(ziplist)和链表(linkedlist),当列表元素个数比较少并且每个元素占用空间比较小的时候,使用压缩列表。当列表元素个数比较多或者某个元素占用空间比较大的时候,使用链表。 考虑到链表的附加空间相对太高,结点的内存也是单独分配的,影响内存管理效率。在Redis3 .2版本开始对列表数据结构进行了改造,使用快速列表(quicklist)代替了压缩列表(ziplist)和链表(linkedlist)。 快速列表(quicklist)是以压缩列表(ziplist)为节点的链表(linkedlist),将链表按段切分,每一段使用压缩列表进行内存的连续存储,多个压缩列表通过prev和next指针组成的双向链表。它结合了压缩列表和链表的优势,进一步压缩了内存的使用量,进一步提高了效率。 下面我们了解一下快速列表的具体实现。 快速列表的实现 在Redis中的快速列表是由quicklist结构表示的,quicklist结构包含由多个快速列表结点组成的双向链表,每一个快速列表结点都保存了一个压缩列表。下面我们一个一个地详细了解一下。 quicklist结构 快速列表是由quicklist结构表示的,它包含以下几个属性: head属性: 指向头部快速列表结点的指针。 tail属性:指向尾部快速列表结点的指针。 count属性:在所有压缩列表中元素的个数总和。 len属性:快速列表结点的个数。 fill属性:压缩列表的最大大小,存放list-max-ziplist-size参数的值。当超出了这个配置,就会新建一个压缩列表。 compress属性:结点压缩深度,存放list-compress-depth参数的值。 bookmarks属性:用来快速列表重新分配内存空间时使用的数组,不使用时不占用空间。 bookmark_count属性:bookmarks数组的大小。 快速列表结点 快速列表结点使用quicklistNode结构表示,它包含以下几个属性: prev属性:指向前一个快速列表结点的指针。 next属性:指向后一个快速列表结点的指针。 zl属性:指向压缩列表的指针,如果当前结点的数据被压缩,那么它指向一个quicklistLZF结构。 sz属性:压缩列表的所占字节总数。 count属性:压缩列表中的元素数量。 encoding属性:存储形式,原生字节数组还是LZF压缩存储。 recompress属性:当查看了某一项被压缩的数据时,需要把数据暂时解压,这时就设置 recompress = 1 做一个标记,等有机会再把数据重新压缩。 quicklistLZF结构 当快速列表结点数据被压缩时,数据会被存放在quicklistLZF结构中,它包含以下几个属性: sz属性:表示压缩后的大小。 compressed属性:存放压缩后的字节数组。 快速列表的压缩机制 在快速列表中,两端结点的数据被访问的可能性比较高,中间结点的数据被访问的可能性比较低。如果我们的应用场景符合这个特点,可以把中间结点的数据使用 LZF 算法进行压缩,从而进一步节省内存空间。我们可以对list-compress-depth参数进行配置。 默认情况下,list-compress-depth参数为0,也就是不压缩数据;当该参数被设置为1时,除了头部和尾部之外的结点都会被压缩;当该参数被设置为2时,除了头部、头部的下一个、尾部、尾部的上一个之外的结点都会被压缩;当该参数被设置为2时,除了头部、头部的下一个、头部的下一个的下一个、尾部、尾部的上一个、尾部的上一个的上一个之外的结点都会被压缩;以此类推。 来源:51CTO博客
-
写在前面 前面我们都是学习MySQL的操作,很少涉及到理论,有些sql语法前面我都没有谈,主要是工作中不常用,一般就是增删查改.要是实际工作中遇到了可以自己稍微查一下,都是很简单的.今天我们谈一下MySQL中被面试官常问的两个部分,都是理论知识,需要我们有自己的理解. 索引 我们先来解释一下什么是索引,这是我们的重点,它是属于MySQL数据库原理层面的知识,如果我们要是自己实现一个数据库,这里我们就要学习的很精通,要是我们岗位只是普通的程序猿,那么了解一下就可以了,至于如何用就不是我们现在这个层次考虑的了. 索引(index),就像是我们书的目录,我们根据目录可以快速的找到我们要看的章节,MySQL也是如此,索引在一定程度上可以加快我们查找数据的速率. 为何出现索引 我们到工作的时候就会发现,你修改数据的次数是远远低于查找数据的次数的,比如我们现在写的博客,一般而言,我写完之后,就很少更改它了,除非是有朋友指出这里存在巨大的错误,我一般都是再重温博客的时候看到有哪里不合适或者错误才会修改,一般都是用来复习和观看的. 同理MySQL也是如此.我们查看是很频繁的.这里就会出现一个问题,对于数据比较少的,我们查早还是很不错的,但是对于公司的服务器而言,这个数据可以实千万级的,那么这个时候我们还是按照老方法查找数据,那么一个命令就要等较长的时间.这时候我们就出现索引,至于索引的原理是什么,这里我们不讨论,知道到这里就可以了. 索引的缺点 前面我们只谈了索引可以提高效率,那么是索引难道就不存在缺点吗?我们想一下,书的目录是不是存在缺点,是的,最直观的一点就是废纸,同理索引是费空间.这就是索引最大的缺点. 随着我们数据量的增大,索引消耗的空间也会越来越大,这还是不是最关键的,对于书来说,我们每一次修改书的内容,那么目录随之也要进行校准,确保可以指定的位置是是准确的,同理MySQL也是如此.不过看起来索引有很大缺点,但是和优点相比较很微小的,瑕不掩瑜.我们在公司里面推荐用索引. 索引的使用 注意,这里的使用只是一点皮毛,甚至连皮毛都算不上,我们不学习使用索引.这里还要和大家谈一个东西,索引的创建最好在创表的时候就出现,要是你在数据比较的多的表来创建索引,那么有极大概率这个数据库会崩,所以要创就在开始的时候创建. 我们先来创建一个数据库,用来查看一下索引. create table student ( id int primary key, name varchar(50), score decimal(3,1));这里我们就可以查看这个数据表的索引了. -- 格式 show index from 表民;show index from student;这里我们就会疑惑了,我们好象是没有添加索引的那么这里为何会出现一个索引,准确来说,我们一个字段被主键或者唯一来约束,这一列就看做一个索引.我们的id就是一个索引.也就是说我们使用主键约束的时候还加快的查早的速率. 同理这里我们也可以给某一列添加索引. -- create index 索引名字 on 表名(列名);create index name_index on student(name); 同理这里我们也可以删除索引,这里只做简单的演示.注意这里容易把数据库给搞挂. drop index name_index on student;索引背后的数据结构 这里才是我们索引的重点,也是面试官比较喜欢问的.这里我们要好好的解释下.我们之前学了一点简单的数据结构,有顺序表,链表,二叉搜索树,哈希表等等,那么我们在想索引的底层是什么? 这里我们首先先排除三个,至于后面的二叉搜索树,可以不可以,这就是我们要讨论的了. 我们感觉二叉搜索树还是挺不错的,不过这里有个问题,我们好象查找数据的时候每一次都要比较,那么如果数据多了,树就高了,对于数据库每一次都意味着文件IO.这里还是不要太行.那么索引的底层究竟是什么?这里我们就要谈一个新的数据结构B+树.不过在谈这个树前,我们先来谈一下B树.注意,我们谈的数据库是MySQL,我这里只知道MySQL的索引是B+树,至于其他的是什么这里就不太清楚了. B/B-树 我们先来解释一下这个名称,B树又叫B-树,记者B-树可不是念B建树,它是B树的另一个名称,从来没有什么B减树.这里算是解决一下我们的疑惑. B树是一个N叉树,这个N叉比较特殊.对于树的每一个节点存在若干个数据把这个节点分为若干个区域.我们这里直接看树的的结构. 一个节点里面存在N个数据,把这个节点分为N+1个区域,每一个区域有指向一个新的节点,这就是B树. 这里我们简单的说一下B树的查找规则,这个和二叉搜索树是一样的,我们先来从根节点出发,根据比较来确定一个一个区域,这里逐渐寻找我们的数据.这里我们就疑惑了,这也是比较,而且比较的次数好象没有变少,那么这里就出现问题了,B树为何会提高索引的效率.这里由于我们还没有分享过文件IO,我先来说下,B树是不是高度变短了,这就就意味着以节点为基础比较变得少了,而磁盘IO也是根据节点的次数来计算的,所以这里提高效率了. B+树 B+树是在B树的基础上再次衍生出来的,基于索引而言,B+树是更加优秀的.我们现来看一下B+树的结构. B+树中每一个父节点的值会作为子节点的最大或者最小值,叶子节节点中会体现出来,而且对于叶子节点而言,我们使用指针把它给串联出来. 这里我们就要下一个结论了,B+树可以说是完美的给MySQL索引设计的,我们看一下它的优点. 树变短了,总体的IO次数变少了 所有的查询终究会落在叶子节点上,查询速度稳定 叶子节点通过链表链接出来后,很适合范围查找 所有的载荷都是放在叶子节点上的,非叶子节点只保存key值. 这里我先来解释一下最后一条,说人话就是我们把所有的数目只保留在在叶子节节点.这样我们的非叶子节点占据的空间很少,甚至可以在在内存中跑,这样也能大大减少磁盘IO,提高速率. 事务 上面总算是把索引谈的差不多了,这里还要接触这个知识点.事物还是一个比较好理解的知识点.我们先来看一下什么是事物. 事物,可以理解成打包,就是把几个工作一起做了,也就是要做都做,要不做都不做. 我们举一个例子,假设我要和自己的女朋哟去约会,首先第一点我要去ATM机中取钱,取完钱之后,我发现我女朋友鸽了我,这时候就是是一个很悲伤的故事.但是如果我们把这两个步骤打包成一个事物,也就是不会存在第一个步骤执行完了第二个步骤不会执行的情况. 原子性 那么我们就有问题了,事物是通过什么来保证的,这就要涉及到原子性了,这个算是线程里面的内容.我先来解释,在过去,人们认为原子是物质的最小单位,这里就用这个来命名了,没有其他的含义.我们再来举一个例子.假设存在一张账户表. 现在我们要做的就是A要给B转500元,就会执行下面的操作.假设第二步的时候出现了问题,也就是A的钱被扣了,但是B没有收到钱,至于造成这样的原因有很多种,比如服务器不小心断电了,数据库崩了等等.显然我们的原子性就是为何避免这种情况的发生. 如何保证事务 事务的保证就是下面的两条规则 要么都执行 要么都不执行 现在我们就疑惑了,我们该如何保证事务,要知道我们执行的结果成不成功是需要执行过之后才发现的,你这个规则好象把路给堵死了,这里的要不都不执行是需要带引号的,所谓的要不都不执行,是我们确实执行,如果成功了,万事大吉,错误了就把他给恢复回去,这种模式叫做回滚.至于如何恢复才是我们重点讨论的.还按照上面的例子来讨论,假设我们执行了第一个步骤,也就是A减去500,执行第二步出现了问题,导致无法执行,我们好象没有给B加上500. 这个时候数据库就会进行回滚,上一个步骤我们给A减去500,回滚的时候给A加上500,让它变回原来的样子.那么请问数据库是如何知道要给A加上500这个正确的操作的,这就又涉及到另外一个东西了.数据库会拿出一个小本本,把过去一段时间的操作记录下来,这就是我们传说中的日志. 事务的使用 我们好象还是没有谈过事务的使用,这里简单看一下就行了,也不是面试官主要的考点. 开启事务:start transaction; 2) 执行多条SQL语句 回滚或提交:rollback/commit 说明:rollback即是全部失败,commit即是全部成功. start transaction;-- 阿里巴巴账户减少2000update accout set mnotallow=money-2000 where name = '阿里巴巴';-- 四十大盗账户增加2000update accout set mnotallow=money+2000 where name = '四十大盗';commit; 事务的特性 面试官最喜欢问的问题就是事务的几个特性,这里我先总结下,后面还有好好谈谈. 原子性 一致性 持久性 隔离行 原子性前面我们已经分析过了,这里我先来谈一下一致性,事务一旦执行,执行的结果必须是合理合法的,也就是说余额不能出现为负数的情况.持久性也就是数据一旦正确存入,就会保存到硬盘中,被持久化存储起了. 隔离性 事务的隔离性在是在并发执行时体现的,并发是我们现在计算机常用的方法. 并发 这里我先来解释一下什么是并发执行.在我们使用计算机的时候,你会发现很多程序都在跑,不过CPU的个数远远要小于程序的个数,这个时候就会出现不够用的问题,并发在一定的程度上解决了这个问题,就是一般一个程序只占据CPU一段时间,然后换下一个. 脏读 这个是我们要重点谈的,可以说是它太重要的.我们先来假设一个场景,我的老师正在那里写代码,准备给我们布置作业,我偷偷的看了一眼,看到一个student类,那时候我就明白了,我们的作业和student类有关.我回去准备相关的知识了,到是在我走后,老师把题目给改了,这就是脏读问题. 不可以重复读 我吃了脏读的亏,这个时候我就比较小心了,我等到老师把代码写完,然后把他给上传到GitHub上,我在GitHub上读代码.这个模式算是老师写的时候我不能读,等到老师写完我读的代码就正确了.但是这里又出现了问题,我们没说毒的时候不能写啊,我在读第二遍的时候,老师把代码给改了.这个时候就是不可以重复的问题. 幻读 我们这个时候和老师在约定一下,我们读的时候你也不能写,这个在一定程度上解决了一不可重复读问题,但是这个真的很完美吗?这个时候老师的等的很无聊,既让我们不能修改原来的代码,那么我这里写另外一个代码总可以了吧. 这个时候又会出现另外一个问题,我们每一次刷新GitHub,有的代码一会有,一会没有,感觉是幻觉一样,这个就是幻读,算是一种特殊的不可重复读问题,要解决这个问题要彻底串行化执行.也就是老师写好了之后,可以直接去摸鱼了,我在这里观看就可以了. 来源:51CTO博客
-
为让更多的朋友了解、参与到openGauss开源社区建设中,并持续提升openGauss资料质量,Gauss松鼠会联合openGauss社区、鲲鹏社区、墨天轮共同开展第二届openGauss资料捉虫活动!报名参与openGauss资料捉虫活动,发现或解决资料中的待改进点,或者推荐他人参与活动,均有机会获奖。参与活动的伙伴不仅每月有机会获得华为无线耳机、华为手环等月度贡献奖,持续输出还有机会获得华为平板、机械键盘等优秀贡献奖。快来参与,让我们看到你的实力!参与方式01 活动报名活动时间:即日起至10月31日报名方式:添加“Gauss松鼠会小助手(ID:Gauss_Asst666)”为好友,发送“报名资料捉虫活动”以及Gitee用户名,即完成报名。02 参与活动方式一:直接参与社区贡献1.提交有效问题(Issue):在openGauss社区资料中寻找待改进的点,在docs仓库提交Issue反馈资料改进意见并在标题前加【openGauss资料捉虫活动】标签。操作指导请参见:cid:link_12.提交有效修改方法(PR,Pull Request) 在openGauss社区资料中寻找待改进的点或对于已存在未解决的Issue问题,在docs仓库按照提交PR修改资料并在标题前加【openGauss资料捉虫活动】标签。操作指导请参见:cid:link_2方式二:推荐他人参与社区贡献1.受邀者完成“openGauss资料捉虫活动”报名并发送邀请者微信昵称给Gauss松鼠会小助手。2.受邀者在openGauss社区提交有效问题(Issue)和修改方法(PR,Pull Request)。奖品设置参与奖提交1个有效的Issue和1个有效的PR,即可获赠华为官方出版的《openGauss数据库核心技术》、《openGauss数据库实战指南》、《openGauss数据库源码解析》书籍三选一,或Gauss松鼠会保温杯、华为三脚架自拍杆二选一。推广奖每邀请2个openGauss社区新用户,且受邀请人成功提交1个有效的Issue和1个有效的PR,邀请人即可获赠以下奖品之一。同一邀请人最多可获得5份礼品。月度贡献奖根据每月新增积分进行排名,定期在Gauss松鼠会公众号公布月度积分排行。贡献奖需要达到30积分以上才能获奖。如果月度参与人数大于50人,则一、二、三等奖品各增加1个,四等奖增加2个。优秀贡献奖根据累积积分进行排名,活动结束后(10月31日),根据总积分情况公布获奖名单。注:1.推广奖与月度贡献奖、优秀贡献奖相互独立,每位参与活动者获奖可叠加。 2.奖品种类数量有限,先到先得。活动规则本次捉虫活动采用积分制,包含如下2部分积分:1、邀请新用户参与活动:每成功邀请一个openGauss社区新用户(未参与过openGauss社区贡献),且受邀人提交1个有效Issue和1个有效的PR,邀请人即可获得20积分,积分依次累加。2、对有效的 Issue 和 PR 进行积分:项目积分规则Issue提交第一个Issue积3分,后续每提交一个Issue积1分。PR提交第一个PR积7分,后续每提交一个PR积2分。有效的Issue或PR的评定请参考:第二届openGauss资料捉虫活动宣传
-
亲爱的伙伴们,经过一个月的激烈角逐,八月份月度贡献奖、推广奖和参与奖获奖名单已经出炉。究竟花落谁家?让我们来看一下8月份的获奖名单:8月份获奖名单月度贡献奖奖项Gitee用户名八月积分一等奖ShawnYan57二等奖企鹅肚皮白白的55changyz55三等奖锁钥50wangwei33刘贵宾30四等奖李雨晴30YvanTan30推广奖推广奖获奖人员名单ShawnYan企鹅肚皮白白的changyz锁钥参与奖参与奖获奖人员名单BubuMumuwangwei孙剑涛磊磊changyzShawnYan一米阳光天影onion_535kewei.shenzhangqnYvanTancftang秋秋molicoderyvan191锁钥企鹅肚皮白白的李雨晴田卫平杨讴YvanTanHashubYC刘贵宾zoneliwt领奖方式1、联系“Gauss松鼠会小助手”(ID:Gauss_Asst666),核对Gitee用户名并进行奖品确认。2、请以上获奖人员提供鲲鹏社区实名认证截图、姓名、联系方式、邮寄地址等信息,以便实物奖的邮寄。3、奖品发放时间:获奖名单公布后的五个工作日内进行奖品发放或邮寄。9月份奖项设置推广奖每邀请2个openGauss社区新用户,且受邀请人成功提交1个有效的Issue和1个有效的PR,邀请人即可获赠以下奖品之一。同一邀请人最多可获得5份礼品。月度贡献奖根据每月新增积分进行排名,定期在Gauss松鼠会公众号公布月度积分排行。贡献奖需要达到30分以上才能获奖。如果月度参与人数大于50人,则一、二、三等奖品各增加1个,四等奖增加2个。优秀贡献奖根据累积积分进行排名,活动结束后(10月31日),根据总积分情况公布获奖名单。注:1.推广奖与月度贡献奖、优秀贡献奖相互独立,每位参与活动者获奖可叠加。 2.奖品种类数量有限,先到先得。参与活动规则点击链接查看:第二届【openGauss资料捉虫】活动等你来报名~不会提PR的小伙伴注意咯,手把手教你提PR教程已发布(点击文末阅读原文)!轻松简单、快速上手的WEB端提交PR教程可供参考,只需花10分钟,便可成功完成提交PR,获得一份参与奖:https://www.bilibili.com/video/BV1kY4y1u7gd/
-
执行引擎一般负责查询的执行,执行引擎在SQL执行栈中起到接收优化器生成的执行计划Plan、并对通过存储引擎提供的数据读写接口,实现对数据进行计算得到查询的结果集。在典型的OLTP场景中,简单查询占了很大一部分比例。这种查询的特征是只涉及单表和简单表达式的查询,因此为了加速这类查询,openGauss提出了SQL by pass框架,在parse层对这类查询做简单的模式判别后,进入到特殊的执行路径里,跳过经典的执行器执行框架,包括算子的初始化与执行、表达式与投影等经典框架,直接重写一套简洁的执行路径,并且直接调用存储接口,这样可以大大加速简单查询的执行速度。SQL by passenable_opfusion用于控制是否对简单增删改查进行优化,简单insert语句在开启enable_opfusion时的执行计划如下由于开启SQL BY PASS,从exec_simple_query过来的语句,会判断可以走SQL BY PASS,否则进入CreatePortal走经典执行流程。static void exec_simple_query(const char* query_string, MessageType messageType, StringInfo msg = NULL) { … /* SQL bypass */ if (runOpfusionCheck) { // 进入SQL by pass (void)MemoryContextSwitchTo(oldcontext); void* opFusionObj = OpFusion::FusionFactory( OpFusion::getFusionType(NULL, NULL, plantree_list), oldcontext, NULL, plantree_list, NULL); if (opFusionObj != NULL) { ((OpFusion*)opFusionObj)->setCurrentOpFusionObj((OpFusion*)opFusionObj); if (OpFusion::process(FUSION_EXECUTE, NULL, completionTag, isTopLevel, NULL)) { CommandCounterIncrement(); finish_xact_command(); EndCommand(completionTag, dest); MemoryContextReset(OptimizerContext); break; } Assert(0); } (void)MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt); } /* * Create unnamed portal to run the query or queries in. If there * already is one, silently drop it. */ portal = CreatePortal("", true, true); // 经典执行流程 … }进入InsertFusion::execute完成数据插入操作。#0 InsertFusion::execute (this=0x7fd93a4104f8, max_rows=9223372036854775807, completionTag=0x7fd933e67020 "@p\346\063\331\177") at opfusion_insert.cpp:297 #1 0x0000000001ac00d9 in OpFusion::fusionExecute (this=0x7fd93a4104f8, msg=0x0, completionTag=0x7fd933e67020 "@p\346\063\331\177", isTopLevel=true, isQueryCompleted=0x0) at opfusion.cpp:453 #2 0x0000000001ac0389 in OpFusion::process (op=0, msg=0x0, completionTag=0x7fd933e67020 "@p\346\063\331\177", isTopLevel=true, isQueryCompleted=0x0) at opfusion.cpp:491 #3 0x000000000193a910 in exec_simple_query (query_string=0x7fd966ad2060 "insert into t1 values(1,200);", messageType=QUERY_MESSAGE, msg=0x7fd933e67210) at postgres.cpp:2624SQL by pass适应的场景有:只支持indexscan和indexonlyscan,且全部WHERE语句的过滤条件都在索引上。只支持单表增删改查,不支持join、using。只支持行存表,不支持分区表,表不支持有触发器。不支持active sql、QPS等信息统计特性。不支持正在扩容和缩容的表。不支持查询或者修改系统列。只支持简单SELECT语句,例如SELECT c3 FROM t1 WHERE c1 = ? and c2 =10;仅可以查询目标表的列,c1和c2列为索引列,后边可以是常量或者参数,可以使用 for update。只支持简单INSERT语句,例如:INSERT INTO t1 VALUES (?,10,?);仅支持一个VALUES,VALUES里面的类型可以是常量和参数,不支持returning。只支持简单DELETE语句,例如:DELETE FROM t1 WHERE c1 = ? and c2 = 10; c1和c2列为索引列,后边可以是常量或者参数。只支持简单UPDATE语句,例如:UPDATE t1 SET c3 = c3+? WHERE c1 = ? and c2 = 10;c3列修改的值可以是常量和参数,也可以是一个简单的表达式,c1和c2列为索引列,后边可以是常量或者参数。经典的执行器关闭enable_opfusion,简单insert的执行计划是这样的在这种执行流程中Portal是执行SQL语句的载体,每一条SQL对应唯一的Portal,不同的查询类型对应的Portal类型也有区别。typedef enum PortalStrategy { PORTAL_ONE_SELECT, // SQL语句包含单一的SELECT查询 PORTAL_ONE_RETURNING, // INSERT/UPDATE/DELETE语句包含Returning PORTAL_ONE_MOD_WITH, // 查询语句包含With PORTAL_UTIL_SELECT, // 工具类型查询语句,如explain PORTAL_MULTI_QUERY // 所有其他类型查询语句 } PortalStrategy;Portal的生命周期管理在exec_simple_query函数中实现,该函数负责Portal创建、执行和清理。Portal执行的主要执行流程包括PortalStart函数、PortalRun函数、PortalDrop函数几个部分。其中PortalStart函数负责进行Portal结构体初始化工作,包括执行算子初始化、内存上下文分配等;PortalRun函数负责真正的执行和运算,它是执行器的核心;PortalDrop函数负责最后的清理工作,主要是数据结构、缓存的清理。PortalRun函数根据查询类型进入不同的处理函数bool PortalRun( Portal portal, long count, bool isTopLevel, DestReceiver* dest, DestReceiver* altdest, char* completionTag) { … switch (portal->strategy) { case PORTAL_ONE_SELECT: … case PORTAL_MULTI_QUERY: // insert从这里进入 PortalRunMulti(portal, isTopLevel, dest, altdest, completionTag); /* Prevent portal's commands from being re-executed */ MarkPortalDone(portal); /* Always complete at end of RunMulti */ result = true; break; … }最终执行ExecInsertT完成数据插入。#0 ExecInsertT (state=0x7fdbf1836060, slot=0x7fdbf0c86460, planSlot=0x7fdbf0c86460, estate=0x7fdbf0c74060, canSetTag=true, options=0, partitionList=0x7fdbf3125860) at nodeModifyTable.cpp:800 #1 0x0000000001a684cd in ExecModifyTable (node=0x7fdbf1836060) at nodeModifyTable.cpp:3043 #2 0x00000000019f3f93 in ExecModifyTableWrap (node=0x7fdbf1836060) at execProcnode.cpp:785 #3 0x00000000019f43b5 in ExecProcNode (node=0x7fdbf1836060) at execProcnode.cpp:1038 #4 0x00000000019ed9d5 in ExecutePlan (estate=0x7fdbf0c74060, planstate=0x7fdbf1836060, operation=CMD_INSERT, sendTuples=false, numberTuples=0, direction=ForwardScanDirection, dest=0x7fdbf13bb9c8, motJitContext=0x0) at execMain.cpp:2163 #5 0x00000000019ea25a in standard_ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0) at execMain.cpp:608 #6 0x000000000181d6ef in explain_ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0) at auto_explain.cpp:121 #7 0x00000000019e9dee in ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0) at execMain.cpp:486 #8 0x000000000194fed6 in ProcessQuery (plan=0x7fdbf0b7b2e0, sourceText=0x7fdbf13ba060 "insert into t1 values(1,200);", params=0x0, isMOTTable=false, motJitContext=0x0, dest=0x7fdbf13bb9c8, completionTag=0x7fdbf3126020 "") at pquery.cpp:292 #9 0x0000000001953fa1 in PortalRunMulti (portal=0x7fdbf0c7a060, isTopLevel=true, dest=0x7fdbf13bb9c8, altdest=0x7fdbf13bb9c8, completionTag=0x7fdbf3126020 "") at pquery.cpp:1889 #10 0x00000000019525e0 in PortalRun (portal=0x7fdbf0c7a060, count=9223372036854775807, isTopLevel=true, dest=0x7fdbf13bb9c8, altdest=0x7fdbf13bb9c8, completionTag=0x7fdbf3126020 "") at pquery.cpp:1191 #11 0x000000000193ac65 in exec_simple_query (query_string=0x7fdbf13ba060 "insert into t1 values(1,200);", messageType=QUERY_MESSAGE, msg=0x7fdbf3126210) at postgres.cpp:2720以上分析了简单insert语句的两种执行流程,对于delete,update,select基本工作流程一致。
-
为让更多的朋友了解、参与到openGauss开源社区建设中,并持续提升openGauss资料质量,Gauss松鼠会联合openGauss社区、鲲鹏社区、墨天轮共同开展第二届openGauss资料捉虫活动!报名参与openGauss资料捉虫活动,发现或解决资料中的待改进点,或者推荐他人参与活动,均有机会获奖。参与活动的伙伴不仅每月有机会获得华为无线耳机、华为手环等月度贡献奖,持续输出还有机会获得华为平板、机械键盘等优秀贡献奖。快来参与,让我们看到你的实力!【参与方式】01 活动报名活动时间:即日起至10月31日报名方式:添加“Gauss松鼠会小助手(ID:Gauss_Asst666)”为好友,发送“报名资料捉虫活动” 以及Gitee用户名,即完成报名。02 参与活动方式一:直接参与社区贡献提交有效问题(Issue):在openGauss社区资料中寻找待改进的点,在docs仓库提交Issue反馈资料改进意见并在标题前加【openGauss资料捉虫活动】标签。操作指导请参见资料捉虫活动指导。提交有效修改方法(PR,Pull Request):在openGauss社区资料中寻找待改进的点或对于已存在未解决的Issue问题,在docs仓库按照提交PR修改资料并在标题前加【openGauss资料捉虫活动】标签。操作指导请参见5分钟教会你如何提交PR:方式二:推荐他人参与社区贡献受邀者完成“openGauss资料捉虫活动”报名并发送邀请者微信昵称给Gauss松鼠会小助手。受邀者在openGauss社区提交有效问题(Issue)和修改方法(PR,Pull Request)。【奖品设置】参与奖提交1个有效的Issue和1个有效的PR,即可获赠华为官方出版的《openGauss数据库核心技术》、《openGauss数据库实战指南》或《openGauss数据库源码解析》书籍一本。推广奖每邀请2个openGauss社区新用户,且受邀请人成功提交1个有效的Issue和1个有效的PR,邀请人即可获赠以下奖品之一。同一邀请人最多可获得5份礼品。贡献奖(月度)根据每月新增积分进行排名,定期在Gauss松鼠会公众号公布月度积分排行。贡献奖需要达到30分以上才能获奖。如果月度参与人数大于50人,则一、二、三等奖品各增加1个,四等奖增加2个。优秀贡献奖根据累积积分进行排名,活动结束后(10月31日),根据总积分情况公布获奖名单。注:推广奖与月度贡献奖、优秀贡献奖相互独立,每位参与活动者获奖可叠加。奖品种类数量有限,先到先得。所有获奖者需在鲲鹏社区完成实名认证后方可领取奖品。【活动规则】本次捉虫活动采用积分制,包含如下2部分积分:邀请好友参与活动,获得相应的积分:每成功邀请一个openGauss社区新用户(未参与过openGauss社区贡献),且受邀人提交1个有效Issue和1个有效的PR,邀请人即可获得20积分,积分依次累加。对有效的 issue 和 PR 进行积分:项目积分规则Issue提交第一个Issue积3分,后续每提交一个Issue积1分。PR提交第一个PR积6分,后续每提交一个PR积2分。附录有效的Issue或PR的评定:Issue或PR已添加“openGauss资料捉虫活动”标签。如果是低错类问题,每个Issue/PR中至少需要包含3处以上错误:问题类型包含但不限于以下规范问题或低错错别字或拼写错误;标点符号使用错误链接错误、空单元格、格式错误英文中包含中文字符表述不通顺,但不影响理解版本号不匹配:如软件包名称、界面版本号上下文描述不一致易用性问题关键步骤错误或缺失,无法指导用户完成任务缺少必要的前提条件、注意事项等描述存在歧义正确性问题技术原理、功能、规格等描述和软件不一致,存在错误原理图、架构图等存在错误命令、命令参数等错误命令无法完成对应功能活动主办方回复为“恭喜您!此Issue有效,感谢您的反馈”或PR经审核后合入到社区表示该Issue或PR有效。活动针对latest版本(当前最新版本),其他版本不参与积分。 重复问题以时间靠前的为准。常见问题:Q1:自己提的Issue被别人提了PR,算违规吗?A1:在开源社区,大家可以自由的提交Issue和PR,都是在为开源社区做贡献,没有违规一说。由于本次是在举办活动,有其特殊性,原则上鼓励并提倡大家针对自己的Issue自己提交PR解决。如果Issue提交超过12小时后仍未解决,则其他人针对此Issue提交的PR有效。Q2:如果我和其他人提交了相同的Issue或PR,我提交的时间早,但是先合入了另一个人的PR导致冲突,积分怎么算?A2:理论上来说先提交Issue和PR的会先合入。但如果后提交的人的PR和Issue先合入了,也会是先提交的Issue和PR积分有效。Q3:同一个文件中的相同问题,拆成多个Issue和PR,这个积分怎么算呢?A3:本次活动旨在让大家在开源社区上贡献,重在发现问题,建议大家同一个页面的问题提交一个Issue。Q4:如果出现相同积分,如何进行排名?A4:积分相同的情况下,以个人最后一个提交早者排名靠前。
-
Gauss松鼠会对外公开招募数据库讲师啦!如果您有一颗乐于分享、专注数据库技术的心,如果您愿意贡献您的一份力量,与我们一同贡献数据库技术交流圈,欢迎您加入Gauss松鼠会讲师团。讲师权益成为Gauss松鼠会讲师,您将获得:评优评先提名Gauss松鼠会年度奖项评选/Gauss松鼠会优化会员评选openGauss举办的各种会议的门票物质报酬华为手机/平板/手表/………讲师需要做什么?Gauss松鼠会目前运营的直播课程主要分为以下几个栏目,您可以自主选择担任任意栏目中的一场或多场直播讲师:高校课堂,讲解内容包含:openGauss应用开发系列课程,包括但不限于:概述,安装部署,基本管理,工具介绍以及备份恢复等。openGauss内核开发系列课程,包括但不限于:内核架构,SQL引擎原理,如何进行内核开发等。大咖讲堂,讲解内容包含:分享数据库前沿技术,可以是本人或所在团队的研究成果,也可以是对数据库发展趋势的洞察。论文分享,讲解内容包含:分析某篇或某个方向的多篇数据库论文,在分享会上进行解读。可以是自己参与写作的论文,也可以是他人的论文。作为直播讲师,您需要:准备直播课件并进行线上直播解答直播间小伙伴的问答讲师申请资格拥有3年以上的数据库从业经验,熟悉数据库技术拥有一颗乐于分享的心,愿意在互联网上分享数据库相关的技术普通话标准,逻辑清晰如何申请微信添加“Gauss松鼠会小助手(ID:Gauss_Asst666)”为好友,发送“讲师报名”。后续我们会和所有报名者联系并确定讲师人选。
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签