• [技术干货] PostgreSQL插件之pg_dirtyread "闪回查询"
    Oracle数据库有时候不小心删除掉数据,想查询这些数据,或者恢复数据,就可以使用带有as of子句的select语句进行闪回查询。PG粉有福了,下面介绍一种类似“闪回查询”插件 pg_dirtyread,可以读取未被vacuum的dead数据。github主页:https://github.com/df7cb/pg_dirtyread1.2 released:https://www.postgresql.org/message-id/20170923211004.uh27ncpjarkucrhd%40msg.credativ.de一、我们一起看下官网的3个例子:语法:SELECT * FROM pg_dirtyread('tablename') AS t(col1 type1, col2 type2, ...);样例1: 删除找回  CREATE EXTENSION pg_dirtyread;     -- Create table and disable autovacuum   CREATE TABLE foo (bar bigint, baz text);        ALTER TABLE foo SET (     autovacuum_enabled = false, toast.autovacuum_enabled = false   );  --测试方便,先把自动vacuum关闭掉。      INSERT INTO foo VALUES (1, 'Test'), (2, 'New Test');     DELETE FROM foo WHERE bar = 1;        SELECT * FROM pg_dirtyread('foo') as t(bar bigint, baz text);    bar   │   baz   ─────┼──────────        1     │ Test        2     │ New Test  可以看到, 被删除的记录(1, 'Test')已经可以查询到。样例2:列被drop的情况  CREATE TABLE ab(a text, b text);     INSERT INTO ab VALUES ('Hello', 'World');        ALTER TABLE ab DROP COLUMN b;     DELETE FROM ab;        SELECT * FROM pg_dirtyread('ab') ab(a text, dropped_2 text);      a   │ dropped_2   ───────┼───────────    Hello │ World    可以看到,虽然b列被drop掉了,但是仍然可以读取到数据。    如何指定列:这里使用dropped_N来访问第N列,从1开始计数。    局限:由于PG删除了原始列的元数据信息,因此需要在表列名中指定正确的类型,这样才能进行少量的完整性检查。包括类型长度、类型对齐、类型修饰符,并且采取的是按值传递。样例3:系统列 SELECT * FROM pg_dirtyread('foo')            AS t(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,            bar bigint, baz text);    tableoid │ ctid  │ xmin │ xmax │ cmin │ cmax │ dead │ bar │        baz   ──────────┼───────┼──────┼──────┼──────┼──────┼──────┼─────┼───────────────────         41823 │ (0,1) │ 1484 │ 1485 │    0 │    0 │ t    │   1 │ Delete   41823 │ (0,2) │ 1484 │    0 │    0 │    0 │ f    │   2 │ Insert         41823 │ (0,3) │ 1484 │ 1486 │    0 │    0 │ t    │   3 │ Update   41823 │ (0,4) │ 1484 │ 1488 │    0 │    0 │ f    │   4 │ Not deleted         41823 │ (0,5) │ 1484 │ 1489 │    1 │    1 │ f    │   5 │ Not updated         41823 │ (0,6) │ 1486 │    0 │    0 │    0 │ f    │   3 │ Updated         41823 │ (0,7) │ 1489 │    0 │    1 │    1 │ t    │   5 │ Not quite updated         41823 │ (0,8) │ 1490 │    0 │    2 │    2 │ t    │   6 │ Not inserted可以看到,xmax和ctid可以被恢复了。 oid只在11以及更早的版本中才能被恢复。二、支持的版本10和11已经支持,2.0以后的版本已经支持12和13,社区还是很活跃。三、实现分析核心代码有2部分:1、dirtyread_tupconvert.c 主要实现了dirtyread_convert_tuples_by_name,通过列名进行元组转换,处理列原信息被清理以及存在表继承的情况,关键部分是数组:attrMap[],下标从1开始。重点分析下dirtyread_do_convert_tupleHeapTuple dirtyread_do_convert_tuple(HeapTuple tuple, TupleConversionMap *map, TransactionId oldest_xmin) { /*  * Extract all the values of the old tuple, offsetting the arrays so that  * invalues[0] is left NULL and invalues[1] is the first source attribute;  * this exactly matches the numbering convention in attrMap.  */ heap_deform_tuple(tuple, map->indesc, invalues + 1, inisnull + 1); //+1是因为是从下标1开始,从旧的元组中把数据的值获取到 /*  * Transpose into proper fields of the new tuple. 这部分是重点,在这里完成转换  */ for (i = 0; i < outnatts; i++) { int j = attrMap; if (j == DeadFakeAttributeNumber)  //场景1:明确是dead,直接调用内核的函数HeapTupleIsSurelyDead即可, //定义在tqual.c中,其它场景可以使用HeapTupleSatisfiesVacuum、HeapTupleSatisfiesMVCC等等,这里明确是dead,所以使用HeapTupleIsSurelyDead { outvalues = HeapTupleIsSurelyDead(tuple , oldest_xmin); outisnull = false; } else if (j < 0) //场景2:系统列,交给函数heap_getsysattr来处理。 outvalues = heap_getsysattr(tuple, j, map->indesc, &outisnull); else {   //场景3:最常见的场景,直接获取即可。 outvalues = invalues[j]; outisnull = inisnull[j]; } } return heap_form_tuple(map->outdesc, outvalues, outisnull); //重新包装为tuple格式 }2、pg_dirtyread.c 面向客户的接口在这里实现。重点分析下 Datum pg_dirtyread(PG_FUNCTION_ARGS)第1部分    if (SRF_IS_FIRSTCALL()),这部分比较套路化     {         superuser校验         PG_GETARG_OID获取表的oid         heap_open打开表         get_call_result_type计算结果校验,不支持复合类型         BlessTupleDesc(tupdesc) 拿到表结构         usr_ctx->map = dirtyread_convert_tuples_by_name(usr_ctx->reltupdesc,                         funcctx->tuple_desc, "Error converting tuple descriptors!");  //关键的一步,这里使用dirtyread_convert_tuples_by_name函数,。         heap_beginscan(usr_ctx->rel, SnapshotAny...),开始启动表扫描,这里使用了SnapshotAny            }第2部分,不断的获取每一行,然后对每一行进行转换,直到扫描结束。     if ((tuplein = heap_getnext(usr_ctx->scan, ForwardScanDirection)) != NULL)     {         if (usr_ctx->map != NULL)         {             tuplein = dirtyread_do_convert_tuple(tuplein, usr_ctx->map, usr_ctx->oldest_xmin);             SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuplein));         }         else             SRF_RETURN_NEXT(funcctx, heap_copy_tuple_as_datum(tuplein, usr_ctx->reltupdesc));     }     else     {         heap_endscan(usr_ctx->scan); //结束扫描         heap_close(usr_ctx->rel, AccessShareLock); //关闭表         SRF_RETURN_DONE(funcctx);     }整体上实现并不是很复杂,理解了这些后,就可以在此基础上增加自己的功能了。 而PG的魅力就在于此--架构的开放性,可以让开发者迅速地开发自己的“小程序”出来。
  • [技术干货] PostgreSQL插件之citext 大小写不敏感
    我们知道,PG对于大小写是敏感的,那有什么办法不敏感呢?可以使用lower函数,例如:SELECT * FROM table1 WHERE lower(col) = LOWER(?);但是存在一些问题:它让你的 SQL 语句冗长,并且你必须总是要记住在列和查询值上使用lower。它不会使用一个索引,除非你使用lower创建一个函数索引。如果你声明一个列为UNIQUE或PRIMARY KEY,隐式生成的索引是大小写敏感的。因此,它对于大小写不敏感的搜索是没有用处的,并且它不会强制大小写不敏感的唯一性。测试了一番:postgres=# create extension citext; CREATE EXTENSION postgres=# CREATE TABLE users ( postgres(#     nick CITEXT PRIMARY KEY, postgres(#     pass TEXT   NOT NULL postgres(# ); CREATE TABLE postgres=# INSERT INTO users VALUES ( 'larry',  sha256(random()::text::bytea) ); ndom()::text::bytea) ); INSERT INTO users VALUES ( 'Bjørn',  sha256(random()::text::bytea) );INSERT 0 1 postgres=# INSERT INTO users VALUES ( 'Tom',    sha256(random()::text::bytea) ); INSERT 0 1 postgres=# INSERT INTO users VALUES ( 'Damian', sha256(random()::text::bytea) ); INSERT 0 1 postgres=# INSERT INTO users VALUES ( 'NEAL',   sha256(random()::text::bytea) ); INSERT 0 1 postgres=# INSERT INTO users VALUES ( 'Bjørn',  sha256(random()::text::bytea) ); INSERT 0 1 postgres=# SELECT * FROM users WHERE nick = 'Larry';  nick  |                                pass                                 -------+--------------------------------------------------------------------  larry | \x479d5f5b2834ea4ee06c545965a828e0933365f3b35ad7d8bd93bdc996636627 (1 row)即使nick列被设置为larry而查询是Larry,SELECT语句也将只返回一个元组。使用了CITEXT类型后,PG的自带函数将以不敏感的方式匹配,例如regexp_*, replace等。限制citext的大小写折叠行为取决于你的数据库的LC_CTYPE设置。因此它如何比较值是在数据库被创建时决定的。在 Unicode 标准定义的术语中没有真正的大小写不敏感。实际上,它的含义是,只要你对你的排序规则满意,你就应该对citext的比较满意。但是如果在你的数据库中存储有不同语言的数据,当排序规则是用于一种语言时,另一种语言的用户可能会发现他们的查询结果并不是所期待的。自PostgreSQL 9.1 其,你可以为citext列或数据值附加一个COLLATE说明。当前,在比较大小写折叠过的字符串时,citext操作符将尊重一种非默认的COLLATE说明,但是最初到小写形式的折叠是根据数据库的 LC_CTYPE设置完成的(就是说,尽管给出了COLLATE "default")。这可能在未来的发行中被改变,这样两步都能遵循输入的COLLATE说明。citext的效率不如text,因为操作符函数和 B 树比较函数必须创建数据的拷贝并且将它转换为小写形式来进行比较。不过,它比使用lower进行大小写不敏感的匹配的效率要略高。如果你在某些环境下需要以大小写敏感的方式比较数据并且在另一些环境下需要以大小写不敏感的方式比较数据,citext就帮不上什么忙。标准的答案是使用text类型并且在你需要以大小写不敏感的方式比较时手工使用lower函数。如果大小写不敏感的比较需求不频繁,这会工作得不错。如果你大部分时间需要大小写不敏感的行为,考虑将数据存储为citext并且在进行大小写敏感比较时显式地将列造型为text。不管在那种情况下,你都需要两个索引来让两种类型的搜索更快。包含citext操作符的模式必须在当前的search_path(通常是public)中。如果它不在搜索路径中,普通的大小写敏感的text操作符将会取而代之。参考:http://www.postgres.cn/docs/11/citext.html
  • [技术干货] PostgreSQL如何实现特定列脱敏
    1      需求有些情况下,有些表的特定列含有敏感数据(如用户信息表中,用户手机号),自然,我们只想让“管理员”用户看到这些敏感数据,其他用户我们希望其看到“处理后的”—— 脱敏的数据。2      实现方案介绍方案1: 使用pg匿名化插件postgresql_anonymizer;方案2: 使用视图进行脱敏;2.1      方案1: 使用pg匿名化插件postgresql_anonymizer(示例来自插件官方文档)-- 修改配置文件:   shared_preload_libraries = 'pg_stat_statements, anon'-- 1. 创建并激活插件CREATE   EXTENSION IF NOT EXISTS anon CASCADE;SELECT   anon.mask_init();-- 2.声明屏蔽的用户CREATE ROLE   skynet;COMMENT ON   ROLE skynet IS 'MASKED';-- 3.声明屏蔽规则COMMENT ON   COLUMN people.name IS 'MASKED WITH FUNCTION anon.random_last_name()';COMMENT ON   COLUMN people.phone IS 'MASKED WITH FUNCTION   anon.partial(phone,2,$$******$$,2)';-- 4. 查询屏蔽敏感信息的用户\! psql test   -U skynet -c 'SELECT * FROM people;' id    |   name   |     phone-----+----------+------------T800 |   n3xtchen | 13******112.2      方案2: 使用视图进行脱敏(示例来自本地开发环境)-- 1. 创建测试用户create user   root;create user   normal_user;-- 2. 切换到root建表 & 视图set role root;create table user_phone_number(id   int, user_name name, phone_number name);insert into   user_phone_number values(1, '张三', '12345678');insert into   user_phone_number values(1, '李四', '56781234');create or   replace view member_phone_number as    SELECT            S.id,            S.user_name,            substring(S.phone_number, 1,1) ||   '******' ||substring(S.phone_number, 8,8) as phone_number    FROM user_phone_number AS S;-- 3. 回收表的权限,授予普通用户view权限revoke all on   user_phone_number from public;grant all on   member_phone_number to normal_user;-- 4. 使用普通用户测试reset role;set role   normal_user;select * from   user_phone_number;select * from   member_phone_number;结果如下:3      优缺点比较总的来看,喜欢“偷懒”、喜欢尝鲜的话,可以使用 postgresql_anonymizer 插件;但如果追求稳定,建议使用视图来实现。4      参考1.         PostgreSQL: 匿名化(Anonymizer)工具 官网:https://labs.dalibo.com/postgresql_anonymizer2.         PostgreSQL: 匿名化(Anonymizer)工具 官方文档: https://postgresql-anonymizer.readthedocs.io/en/stable/
  • [技术干货] 什么是云数据库RDS?云数据库RDS有什么用?
    下面以华为云数据库RDS为例,来了解一下云数据库RDS是什么,云数据库RDS有什么用?云数据库RDS(ApsaraDB for RDS,简称RDS)是一种稳定可靠、可弹性伸缩的在线数据库服务。基于飞天分布式系统和全SSD盘高性能存储,支持MySQL、SQL Server、PostgreSQL和PPAS(高度兼容Oracle)引擎,默认部署主备架构且提供了容灾、备份、恢复、监控、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼!云数据库RDS的价格因市场走势而实时变动,要了解华为云数据库RDS的实时价格,请进入华为云数据库RDS详情页面(页面直达链接:9i0i.cn/huaweicloud)了解。为什么选择云数据库RDS:选择云数据库RDS,您可以快速搭建稳定可靠的数据库服务,相比自建数据库有如下优势:便宜易用,具有灵活计费、按需变配、即开即用等优点。高性能,包括参数优化、SQL优化建议等。高可用架构和多种容灾方案。高安全性,提供多种安全措施保障数据安全。在性价比、可用性、可靠性、易用性、性能等方面,云数据库RDS都有很大优势,价格相比ECS自建数据库,仅需约1/3,相比自购服务器搭建数据库,仅需约1/10。云数据库RDS都有哪些应用场景?云数据库RDS可以在数据上和华为云诸多云产品打通,实现多样化的能力扩展数据异地容灾场景:通过数据传输服务,用户可以将自建机房的数据库实时同步到公有云上任一地域的RDS实例里面。即使发生机房损毁的灾难,数据永远在华为云有一个备份。 读写分离场景:应用读取请求较高,或是需要应对短期内读取流量高峰,可在RDS for MySQL实例下挂载只读实例,每个只读实例拥有独立的链接地址,由应用端自行实现读取压力分配。多结构数据存储:在数据类型多样的应用中,可将高热存取数据存储于缓存产品,如云数据库Memcached版 、云数据库Redis版,将图片等非结构化资源存储于对象存储 OSS,而将链接等结构化数据存储于RDS,实现对业务数据高效存取,并相应降低成本投入。搜索引擎场景:针对应用数据量较大,且有较多复杂关键词搜索场景,可搭配使用开放搜索,对亿级别数据实现百毫秒内搜索。大数据计算:云数据库RDS搭配E-MapReduce,运行Hadoop、Spark分析RDS中数据,满足如日志分析、数据仓库、商业智能、机器学习、科学模拟等业务需求。
  • [技术干货] Postgres社区版本策略
    总有同事问我社区的版本计划,以及如何选择版本,今天就把这个事情说明白下。一、主版本策略Major Version(DBA习惯叫大版本):每年1个版本,且每个版本只维护5年。所以去年新出版本12,今天13,后年就是14。在10之前,版本是2位,例如,以9.2,9.5,9.6 这样的方式命名,其中9.6是最后一个。VersionCurrent minorSupportedFirst ReleaseFinal Release1212.4YesOctober 3, 2019November 14, 20241111.9YesOctober 18, 2018November 9, 20231010.14YesOctober 5, 2017November 10, 20229.69.6.19YesSeptember 29, 2016November 11, 20219.59.5.23YesJanuary 7, 2016February 11, 20219.49.4.26NoDecember 18, 2014February 13, 20209.39.3.25NoSeptember 9, 2013November 8, 20189.29.2.24NoSeptember 10, 2012November 9, 20179.19.1.24NoSeptember 12, 2011October 27, 20169.09.0.23NoSeptember 20, 2010October 8, 20158.48.4.22NoJuly 1, 2009July 24, 20148.38.3.23NoFebruary 4, 2008February 7, 20138.28.2.23NoDecember 5, 2006December 5, 20118.18.1.23NoNovember 8, 2005November 8, 20108.08.0.26NoJanuary 19, 2005October 1, 20107.47.4.30NoNovember 17, 2003October 1, 20107.37.3.21NoNovember 27, 2002November 27, 20077.27.2.8NoFebruary 4, 2002February 4, 20077.17.1.3NoApril 13, 2001April 13, 20067.07.0.3NoMay 8, 2000May 8, 20056.56.5.3NoJune 9, 1999June 9, 20046.46.4.2NoOctober 30, 1998October 30, 20036.36.3.2NoMarch 1, 1998March 1, 2003参考:https://www.postgresql.org/support/versioning/二、Minor Version (小版本策略)每个季度一个,否则这些发行版的目标日期是2月,5月,8月和11月的第二个星期四。当前即将发布的时间表是:November 12th, 2020February 11th, 2021May 13th, 2021August 12th, 2020参考:https://www.postgresql.org/developer/roadmap/三、版本选择PG的版本稳定、质量可靠,新增应用,可以放心的选择最新版本。保守点的话,就选择上一年的吧,再往前就不推荐了。
  • [热门活动] 828企业上云节-数据上云全场景覆盖,华为云助力企业智能化升级
    当下,数字经济来临,新技术带来便利的同时,更多的企业面临着机遇和挑战。从社会趋势来讲,生产要素已由农业经济发展到工业经济再到数字经济,数据成为新生产要素,智能成为新生产力。 从Gartner趋势分析表明,企业面临着资源分散、数据不通、应用孤立等问题,这类烟囱式应用和数据孤岛已成为企业数字化转型的阻碍;企业数据逐步多元化,数字化业务井喷增长,驱动企业需要构建一个跨越多域数据、简单、一致的数字化运营生态系统。随着技术的发展,探索数据价值一直在持续,数据平台技术架构也逐步在进化。华为云针对企业上云与治理提出了一套适用于互联网、金融、游戏、产业云等行业的解决方案,数据采集到数据处理与汇聚,再到数据计算与分析,最后到应用与消费层,通过对数据的一系列操作(采集、处理、分析和应用),构建了全场景数据服务助力企业数字化转型,最终实现从数据到价值的闭环。                                               图1 数据技术平台整体技术架构 数据采集与处理对核心关键应用如ERP、CRM、PDM等产生的数据来讲,经过数据复制服务DRS采集后,迁移至云上数据库,华为云数据库具备轻松实现存储容量扩容、快速便捷的实例规格变更,内核深度优化,业务并发量1000+时性能依然保持稳定,扩容仅需几分钟。具有超高的数据可靠性等特点,保障客户业务稳定运行。对于邮件,文档,网页,监控、车辆等非结构化数据,此类面向分析型场景,将通过实时数据接入kafka等服务进行数据采集,可存入对象存储服务OBS,通过流查询,交互式查询等方式,对数据进行挖掘和批处理和批计算。同时以全栈大数据MapReduce服务为基础,提供一站式大数据平台解决方案,一键式构筑数据接入、数据存储、数据分析和价值挖掘的统一大数据平台,并且与华为云IOT物联网、ROMA平台、数据湖工厂及数据可视化等服务对接,轻松解决数据通道上云、大数据作业开发调度和数据呈现的困难,使用户从复杂的大数据平台构建和专业大数据调优和维护中解脱出来,更加专注行业应用,完成一份数据多业务场景使用的诉求,实现自动伸缩,按需使用和计算存储分离,更低成本更高性能。数据分析与应用面向操作型场景,数据库的管理可以由数据管理服务DAS实现,DAS是用来登录和操作数据库的Web服务,提供数据库运维开发功能以及 DevOPS服务。为方便用户使用和运维华为云RDS,提供数据和表结构的同步、在线编辑,SQL输入的智能提示等丰富的数据库开发功能。同时面向大企业提供基于权限最小化控制和审批流程机制,提供数据保护、变更审核、操作审计、研发自助化等数据库DevOPS平台,帮助企业实现大规模数据库下的标准化、规范化、高效率、超安全的管理手段。面向分析型场景中,用于计算与分析的数据仓库服务GaussDB(DWS),是实时、简单、安全可信的企业级融合数据仓库,可借助GaussDB(DWS) Express将查询分析扩展至数据湖。华为云数据上云方案,可实现贯穿数据全流程一站式开发运营平台,提供全域数据集成、标准数据规范架构研发、连接并萃取数据价值、统一数据资产管理、数据智能分析与可视化、数据开放服务,可帮助企业构建完整数据**解决方案。同时跨源分析选择数据湖探索DLI服务,数据免搬迁,是完全兼容Apache Spark和Apache Flink生态, 实现批流一体的Serverless大数据计算分析服务,无需大数据背景,会SQL就会大数据分析。通过一系列流转将数据转化为资产,企业将IT系统、数据及IT服务集中到统一的云管资源池中,将会提高提升整体资源利用率和工作效率,改善流程,降低运营成本。号外:828企业上云节,来企业数据上云和治理专场,数据上云难题一站式解决,不但有亿元上云补贴,还有新购满额送华为手机P40 Pro 5G,更多豪礼等你来拿~扫码立即抢购,还可免费获取超高价值的产品白皮书噢!
总条数:36 到第
上滑加载中