项目经验分享|openGauss 陈贤文:受益于开源,回馈于开源
开源之夏
项目经验分享
2023 #08

# 关于 openGauss 社区
openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验,结合企业级场景需求,持续构建竞争力特性。同时openGauss也是一个开源的数据库平台,鼓励社区贡献、合作。官网: opengauss.org
# 项目基本信息
项目名称:openGauss权限扫描
项目导师:崔永泉
项目描述:根据openGauss的数据库配置和用户权限,检查数据库中是否存在违规操作的可能和安全隐患。
# openGauss-安全管理机制笔记 主要内容: openGauss数据库权限管理模型、权限规划示例、权限识别项目具体实施方法。 openGauss数据库权限管理模型 由于数据库中存储着大量重要数据和各类敏感信息,并且为持有不同权限的合法用户提供数据共享服务,这就要求数据库具备完善的安全防御机制来抵抗来自内部和外部的恶意攻击,以保障数据不丢失、隐私不泄露以及数据不被篡改等。当前openGauss数据库已经构建了纵深防御的安全体系,保障数据库在应用中的安全。完善的权限管理机制可以有效阻断恶意用户的越权操作。 常见的权限控制模型有三种:基于策略的访问控制模型,基于角色的访问控制模型以及基于会话和角色的访问控制模型。openGauss数据库采用基于角色的权限访问控制模型(RBAC),利用角色来组织和管理权限,能够大大简化对权限的授权管理。借助角色机制,当给一组权限相同的用户授权时,只需将权限授予角色,再将角色授予这组用户即可,不需要对用户逐一授权。而且利用角色权限分离可以很好地控制不同用户拥有不同的权限,相互制约达到平衡。
基于角色的权限访问控制模型(RBAC)
RBAC思想简单地说,一个用户拥有若干角色,每一个角色拥有若干权限,每一个角色拥有若干个菜单,这样,就构造成“用户-角色-权限”、“角色-菜单” 的授权模型。在这种模型中,用户与角色、角色与权限、角色与菜单之间构成了多对多的关系。 在openGauss数据库中,用户和角色是基本相同的概念,唯一的区别是在创建角色的时默认没有LOGIN权限,也不会自动创建同名的模 ,也就是说一个拥有LOGIN权限的角色可以被认为是一个用户。在以下的介绍中我们统一通过用户(USER) 来连接、访问数据库以及执行SQL,通过角色(ROLE)来组织和管理权限。我们通过将不同的权限打包成角色授予用户,使得用户获得该角色中的所有权限。同时通过改变角色的权限,该角色所包含的所有成员的权限也会被自动修改。
在openGauss数据库系统中权限分为两种:系统权限和对象权限。
系统权限是指系统规定用户使用数据库的权限,比如登录数据库、创建数据库、创建用户/角色、创建安全策略等。
对象权限是指在数据库、模式、表、视图、函数等数据库对象上执行特殊动作的权限,不同的对象类型与不同的权限相关联,比如数据库的连接权限,表的查看、更新、插入等权限,函数的执行权限等。基于特定的对象来描述对象权限才是有意义的。
系统权限
系统权限又称用户属性,具有特定属性的用户会获得指定属性所对应的权限。系统权限无法通过角色(ROLE)被继承。在创建用户或角色时可以通过SQL语句CREATE ROLE/USER指定用户具有某些属性,或者通过ALTER ROLE/USER的方式给用户/角色添加用户属性或取消用户属性。
openGauss数据库支持如下系统权限的授予和回收:
openGauss提供SQL语句CREATE/ALTER ROLE/USER实现系统权限的授予和回收,示例如下:
#例2:授予角色role1监控管理员的权限,同时取消创建数据库的权限 openGauss=# ALTER ROLE role1 WITH MONADMIN NOCREATEDB; ALTER ROLE
#例3:查看系统表pg_authid或系统视图pg_roles获取角色role1的相关信息 openGauss=# SELECT rolname,rolcreatedb,rolmonitoradmin FROM pg_authid WHERE rolname= 'role1'; rolname | rolcreatedb | rolmonitoradmin ---------+-------------+----------------- role1 | f | t (1 row)
对象权限
对象所有者缺省具有该对象上的所有操作权限,比如修改、删除对象的权限,查看对象的权限,将对象的操作权限授予其他用户,或撤销已经授予的操作权限等。其中对象的ALTER、 DROP、COMMENT、INDEX、VACUUM以及对象的可再授予权限属于所有者固有的权限,隐式拥有。但对象所有者可以撤消自己的普通权限,例如,使表对自己以及其他人都只可读。
对象权限可以通过角色(ROLE)被继承,这样方便用户将这些单个的权限打包成一个角色进行权限管理。openGauss数据库针对每一类数据库对象支持如下对象权限:

openGauss提供SQL语句GRANT/REVOKE实现对象权限的授予和回收:
#例1:将对表tbl1进行select的权限以及将select再赋权的权限授予用户user1, #赋权后用户user1有权对tbl执行select操作且user1有权限将select权限再赋予其他用户 [omm@home ~]$ gsql -d testdb -c "GRANT select ON TABLE test.tbl1 TO user1 WITH GRANT OPTION" GRANT [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1" ERROR: permission denied for schema test LINE 1: select * from test.tbl1 ^ DETAIL: N/A #如上因为user1没有test模式的usage权限,所以即便给他授权了模式下的表的select权限也访问不了 gsql -d testdb -c "GRANT usage ON schema test TO user1" [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO user1" GRANT [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1" id ---- 1 2 3 (3 rows)
#此时user1没有对表alter、drop的权限 [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "drop table test.tbl1" ERROR: permission denied for relation tbl1 DETAIL: N/A [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "alter table test.tbl1 add column name text" ERROR: permission denied for relation tbl1 DETAIL: N/A
#例2:将对表tbl1进行alter和drop的权限赋给用户user1 #赋权后用户user1有权对tbl1进行修改(ALTER)和删除(DROP)操作 [omm@home ~]$ gsql -d testdb -c "GRANT alter, drop ON TABLE test.tbl1 TO user1;" GRANT [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "alter table test.tbl1 add column name text" ALTER TABLE
#例3:撤销用户user1对表tbl进行select的权限 [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1" id | name ----+------ 1 | 2 | 3 | (3 rows)
[omm@home ~]$ gsql -d testdb -c "REVOKE select ON test.tbl1 FROM user1" REVOKE #撤销后用户user1对tbl进行select操作会报错: [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select * from test.tbl1" ERROR: permission denied for relation tbl1 DETAIL: N/A 本次项目的目的就在于区分对象权限的情况:
CREATE USER
通过CREATE USER创建的用户,默认具有LOGIN权限。
通过CREATE USER创建用户的同时,系统会在执行该命令的数据库中,为该用户创建一个同名的SCHEMA。
- 系统管理员在普通用户同名schema下创建的对象,所有者为schema的同名用户(非系统管理员)。
CREATE ROLE
- 角色是拥有数据库对象和权限的实体。在不同的环境中角色可以认为是一个用户,一个组或者兼顾两者。
- 在数据库中添加一个新角色,角色无登录权限。
创建角色的用户必须具备CREATE ROLE的权限或者是系统管理员。
schema
Schema又称作模式。通过管理Schema,允许多个用户使用同一数据库而不相互干扰,可以将数据库对象组织成易于管理的逻辑组,同时便于将第三方应用添加到相应的Schema下而不引起冲突。
伴随着数据库的发展以及所面向业务场景的扩展,对数据库权限分离以及权限管理的细粒度划化提出了更高的要求,为了满足多样化用户的业务安全要求,openGauss数据库针对权限模型进行了更细粒度的权限划分,使得用户可以更灵活地依据实际业务进行用户权限分配和管理,除了基本系统权限和对象权限的划分外,还有一些高阶的权限管理机制用来满足客户的业务诉求,比如三权分立机制。
openGauss安装完成后会得到一个具有最高权限的超级用户。数据库超级用户的高权限意味着该用户可以做任何系统管理操作和数据管理操作,甚至可以修改数据库对象,包括接下来将要介绍的审计日志信息。对于企业管理来说, 手握超级用户权限的管理人员可以在无人知晓的情况下改变数据行为,这带来的后果是不可想象的。
在上文提到,初始化用户不允许远程登录,仅可本地登录。那么,在组织行为上由IT 部门严格监控拥有该权限的员工在本地的操作行为,就可有效避免诸如修改表中数据等“监守自盗”行为的发生。为了实际管理需要,在数据库内部就需要其他的管理员用户来管理整个系统,如果将大部分的系统管理权限都交给某一个用户来执行,实际上也是不合适的,因为这等同于超级用户。
为了很好地解决权限高度集中的问题,在openGauss系统中引入三权分立角色模型,如图所示。三权分立角色模型最关键的三个角色为安全管理员、系统管理员和审计管理员。其中,安全管理员用于创建数据管理用户;系统管理员对创建的用户进行赋权;审计管理员则审计安全管理员、系统管理员、普通用户实际的操作行为。
通过三权分立角色模型实现权限的分派,且三个管理员角色独立行使权限,相互制约制衡。使得整个系统的权限不会因为权限集中而引入安全的风险。
事实上,产品使用过程中的安全是技术本身与组织管理双重保障的结果,在系统实现三权分立模型后,需要有三个对应的产品自然人分别握有对应的账户信息,以达到真正权限分离的目的。
三权分立是对系统权限管理机制的补充,核心思想是将管理数据库对象的权限、管理用户的权限和管理审计日志的权限分离,从而避免一个管理员拥有过度集中的权利带来的高风险。通过将GUC参数enableSeparationOfDuty设置为on来打开三权分立开关。
openGauss=# select name,setting,unit,context from pg_settings where name ~ 'enableSeparationOfDuty'; name | setting | unit | context ------------------------+---------+------+------------ enableSeparationOfDuty | off | | postmaster (1 row) 三权分立开关打开后,SYSADMIN的权限范围将缩小,不再包括允许创建用户/角色的权限,也不再包括允许查看、删除数据库审计日志的权限。SYSADMIN,CREATEROLE,AUDITADMIN三种系统权限的权限范围互相隔离,互不影响,而且一个用户仅能被赋予其中一个属性。 三权分立打开后的权限范围如下:
列级访问控制
在一些业务场景中,数据表中的某些列存储了重要的信息,需要对用户不可见,但其他列的数据又需要用户能够查看或操作,此时就需要针对数据表的特定列做访问控制,实现针对用户的列级别的访问控制。
#创建测试数据 gsql -d postgres -r create database testdb; \c testdb create user test identified by 'test@123'; create user user1 identified by 'test@123'; alter database testdb owner to test; set search_path to test; create table tbl (id int,name varchar(20)); insert into tbl values(1,'test1'),(2,'test2'),(3,'test3');#例1:将对表tbl的第一列(id)进行select的权限和对表tbl的第二列(name)进行update的权限授予用户user1 #赋权后用户user1有权对tbl的第一列执行select操作和对第二列执行update操作 [omm@home ~]$ gsql -d testdb -c "GRANT select(id),update(name) ON TABLE test.tbl TO user1;" GRANT [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl" ERROR: permission denied for schema test LINE 1: select id from test.tbl ^ DETAIL: N/A #如上因为user1没有test模式的usage权限,所以即便给他授权了模式下的表的select权限也访问不了 [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO user1" GRANT [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl" id ---- 1 2 3 (3 rows) [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select name from test.tbl" ERROR: permission denied for relation tbl DETAIL: N/A
[omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "update test.tbl set name = 'haha' where id=3" UPDATE 1 [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "update test.tbl set id = 4 where id=3" ERROR: permission denied for relation tbl DETAIL: N/A #例2:撤销用户user1对表tbl的第一列id进行select的权限 #撤销后用户user1不再具有查看表tbl的第一列id数据的权限 [omm@home ~]$ gsql -d testdb -c "REVOKE select(id) ON test.tbl FROM user1" REVOKE [omm@home ~]$ gsql -d testdb -U user1 -W test@123 -c "select id from test.tbl" ERROR: permission denied for relation tbl DETAIL: N/A
行级访问控制
set search_path to test; #步骤1:创建信息表pat_info记录医院病人的个人信息: create table pat_info(patience varchar(20),doctor varchar(20),age int); insert into pat_info values('peter','mary',25),('bob','mary',56),('julie','tom',38)
#查询表数据 [omm@home ~]$ gsql -d testdb -U test -W test@123 -c "select * from test.pat_info" patience | doctor | age ----------+--------+----- peter | mary | 25 bob | mary | 56 julie | tom | 38 (3 rows)
#步骤2:创建行级访问控制策略,使得医生只能查看属于自己的病人信息: [omm@home ~]$ gsql -d testdb -c "CREATE ROW LEVEL SECURITY POLICY rls_select ON test.pat_info FOR select USING(doctor=current_user)" CREATE ROW LEVEL SECURITY POLICY
#步骤3:打开信息表pat_info上的行级访问控制开关 [omm@home ~]$ gsql -d testdb -c "ALTER TABLE test.pat_info ENABLE ROW LEVEL SECURITY;" ALTER TABLE
#步骤4:将信息表pat_info的查看权限赋予所有人 [omm@home ~]$ gsql -d testdb -c "grant select on table test.pat_info to public;" GRANT
#步骤5:Mary医生的查看结果: [omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info" ERROR: permission denied for schema test LINE 1: select * from test.pat_info ^ DETAIL: N/A [omm@home ~]$ [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO mary" GRANT [omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info" patience | doctor | age ----------+--------+----- peter | mary | 25 bob | mary | 56 (2 rows)
#Tom医生的查看结果: [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO tom" GRANT [omm@home ~]$ gsql -d testdb -U tom -W test@123 -c "select * from test.pat_info"
- 行级访问控制
在实际业务中还存在另外一种场景,同一张数据表,只允许用户查看满足特定条件的行数据,此时就需要将访问控制精确到数据表的行级别,使得不同用户执行相同的SQL查询、更新或删除操作,读取到的结果是不同的。
用户可以在数据表上创建行级访问控制(row level security)策略,该策略是针对特定数据库用户、特定SQL操作生效的表达式。当数据库用户访问数据表时,满足策略条件的行对用户可见,不满足条件的行对用户不可见,从而实现针对用户的行级别的访问控制。
openGauss提供SQL语句CREATE/ALTER/DROP ROW LEVEL SECURITY进行行级访问权限策略的创建/修改/删除操作:set search_path to test; #步骤1:创建信息表pat_info记录医院病人的个人信息: create table pat_info(patience varchar(20),doctor varchar(20),age int); insert into pat_info values('peter','mary',25),('bob','mary',56),('julie','tom',38)
#查询表数据 [omm@home ~]$ gsql -d testdb -U test -W test@123 -c "select * from test.pat_info" patience | doctor | age ----------+--------+----- peter | mary | 25 bob | mary | 56 julie | tom | 38 (3 rows)
#步骤2:创建行级访问控制策略,使得医生只能查看属于自己的病人信息: [omm@home ~]$ gsql -d testdb -c "CREATE ROW LEVEL SECURITY POLICY rls_select ON test.pat_info FOR select USING(doctor=current_user)" CREATE ROW LEVEL SECURITY POLICY #步骤3:打开信息表pat_info上的行级访问控制开关 [omm@home ~]$ gsql -d testdb -c "ALTER TABLE test.pat_info ENABLE ROW LEVEL SECURITY;" ALTER TABLE #步骤4:将信息表pat_info的查看权限赋予所有人 [omm@home ~]$ gsql -d testdb -c "grant select on table test.pat_info to public;" GRANT #步骤5:Mary医生的查看结果: [omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info" ERROR: permission denied for schema test LINE 1: select * from test.pat_info ^ DETAIL: N/A [omm@home ~]$ [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO mary" GRANT [omm@home ~]$ gsql -d testdb -U mary -W test@123 -c "select * from test.pat_info" patience | doctor | age ----------+--------+----- peter | mary | 25 bob | mary | 56 (2 rows)
#Tom医生的查看结果: [omm@home ~]$ gsql -d testdb -c "GRANT usage ON schema test TO tom" GRANT [omm@home ~]$ gsql -d testdb -U tom -W test@123 -c "select * from test.pat_info"
权限规划示例
将测试用例全部移植完成,本次移植涉及7个测试文件、全部功能接口和搜索选项、近3000行代码,针对实机进行单元测试,发现其中的不符合预期的功能接口,针对性进行调试适配,确保功能可用。最后整理测试报告TESE.md文件,列明测试用例涉及的接口和实机测试结果。
本示例以项目维度进行权限管理示例。
DBA拥有open Gauss实例的高权限账号,名称是dbsuperuser。
举例业务项目名称是oaauth,OA系统,新建schema名称是oaauth、oaauth_1。
项目中新增的资源owner账号和角色Role规划如下:
新增业务账号时,根据不同需求,采用如下管理模式创建:
- oaauth_readwrite = oaauth_role_readwrite + login权限
- oaauth_readonly = oaauth_role_readonly + login权限
配置步骤
1. 创建项目资源owner账号oaauth_owner和项目Role。 DBA使用dbsuperuser高权限账号执行如下操作。CREATE ROLE oaauth_role_readwrite; CREATE ROLE oaauth_role_readonly;
--- 设置: 对于oaauth_owner 创建的表,oaauth_role_readwrite 有 DQL(SELECT)、DML(UPDATE、INSERT、DELETE)权限。 ALTER DEFAULT PRIVILEGES FOR ROLE oaauth_owner GRANT ALL ON TABLES TO oaauth_role_readwrite;
--- 设置: 对于oaauth_owner 创建的SEQUENCES,oaauth_role_readwrite 有 DQL(SELECT)、DML(UPDATE、INSERT、DELETE)权限。 ALTER DEFAULT PRIVILEGES FOR ROLE oaauth_owner GRANT ALL ON SEQUENCES TO oaauth_role_readwrite;
--- 设置: 对于 oaauth_owner 创建的表, oaauth_role_readonly 只有 DQL(SELECT)权限。 ALTER DEFAULT PRIVILEGES FOR ROLE oaauth_owner GRANT SELECT ON TABLES TO oaauth_role_readonly; 2. 创建oaauth_readwrite、oaauth_readonly业务账号。 DBA使用dbsuperuser高权限账号执行如下操作。
--- oaauth_readwrite只有 DQL(SELECT)、DML(UPDATE、INSERT、DELETE)权限。 CREATE USER oaauth_readwrite WITH LOGIN PASSWORD 'dfandfnapSDhf23hbEfabf'; GRANT oaauth_role_readwrite TO oaauth_readwrite;
--- oaauth_readonly只有 DQL(SELECT)权限。 CREATE USER oaauth_readonly WITH LOGIN PASSWORD 'F89h912badSHfadsd01zlk'; GRANT oaauth_role_readonly TO oaauth_readonly;
3. 创建schema oaauth,并授权给项目Role。
DBA使用dbsuperuser高权限账号执行如下操作。
--- schema oaauth的owner是 oaauth_owner账号 CREATE SCHEMA oaauth AUTHORIZATION oaauth_owner;--- 授权ROLE相关SCHEMA访问权限。 GRANT USAGE ON SCHEMA oaauth TO oaauth_role_readwrite; GRANT USAGE ON SCHEMA oaauth TO oaauth_role_readonly;
说明:
oaauth_readwrite和oaauth_readonly自动继承了相关Role的权限变更,不需要再额外操作。
应用场景示例
场景1:使用oaauth_owner账号:对schema oaauth中的表进行DDL(CREATE、DROP、ALTER)操作说明:
业务层做读写分离,避免了自动读写分离中间件proxy带来的额外成本和性能损耗。
即使目前还没有使用只读实例,也建议区分 readonly客户端、readwrite客户端,为使用只读实例做准备。readonly客户端建议使用readonly账号,最小权限原则,规避权限误用。
– readonly客户端,使用readonly账号,设置JDBC URL:只读实例1地址,只读实例2地址,读写实例地址。
– readwrite客户端,使用readwrite账号,设置JDBC URL:读写实例地址。
使用oaauth_readwrite账号,对schema oaauth中的表进行DQL(SELECT)、DML(UPDATE、INSERT、DELETE)操作:
--- oaauth_readwrite没有 DDL(CREATE、DROP、ALTER)权限 CREATE TABLE oaauth.test2(id int); ERROR: permission denied for schema oaauth LINE 1: create table oaauth.test2(id int);
DROP TABLE oaauth.test; ERROR: must be owner of table test
ALTER TABLE oaauth.test ADD id2 int; ERROR: must be owner of table test
CREATE INDEX idx_test_name on oaauth.test(name); ERROR: must be owner of table test
使用oaauth_readonly账号,对schema oaauth中的表进行DQL(SELECT)操作:
SELECT id,name FROM oaauth.test LIMIT 1; id | name ----+------- 1 | name0 (1 row)
场景3:不同项目交叉授权
如果有另外1个项目employee,需求为账号employee_readwrite增加oaauth项目的表只读权限。DBA使用dbsuperuser高权限账号做如下操作:--- 给账号 employee_readwrite 加上 oaauth_role_readonly 权限集合。 GRANT oaauth_role_readonly TO employee_readwrite; 场景4:项目新增 schema oaauth_2,并授权给项目Role oaauth_readwrite、oaauth_readonly、employee_readwrite账号自动继承了相关Role的权限变更,不需要再额外操作。DBA使用dbsuperuser 高权限账号做如下操作:
CREATE SCHEMA oaauth_1 AUTHORIZATION oaauth_owner;
--- 授权ROLE相关SCHEMA访问权限。 --- CREATE 使得 oaauth_role_admin 对schema oaauth_1中的表有 DDL(CREATE、DROP、ALTER)权限。 GRANT USAGE ON SCHEMA oaauth_1 TO oaauth_role_readwrite; GRANT USAGE ON SCHEMA oaauth_1 TO oaauth_role_readonly; 账号权限查询
通过本文介绍的账号权限管理模型创建的账号,可以通过如下方式查询具体权限信息。
使用PostgreSQL客户端命令行终端连接RDS PostgreSQL数据库,具体请参见连接PostgreSQL实例 。然后使用\du命令查看:
从上述查询结果示例中可以看出:employee_readwrite账号的Member of列中,内容为oaauth_role_readonly,employee_role_readwrite,因此,此账号对employee项目表具有DQL和DML权限,对oaauth项目表具有DQL权限。
使用SQL查询:
用户权限查询实例
查询用户:\du

查询用户opengauss的数据库的权限:
opengauss=# select a.datname,b.rolname,string_agg(a.pri_t,',') from (select datname,(aclexplode(COALESCE(datacl, acldefault('d'::"char",datdba)))).grantee as grantee,(aclexplode(COALESCE(datacl, acldefault('d'::"char", datdba)))).privilege_type as pri_t from pg_database where datname not like 'template%') a,pg_roles b where (a.grantee=b.oid or a.grantee=0) and b.rolname='opengauss' group by a.datname,b.rolname;datname | rolname | string_agg ---------------+-----------+-------------------------------------------- testdb | opengauss | TEMPORARY,CONNECT db_department | opengauss | TEMPORARY,CONNECT postgres | opengauss | TEMPORARY,CONNECT opengauss | opengauss | TEMPORARY,CONNECT,CREATE,TEMPORARY,CONNECT (4 rows)
显示用户opengauss对于opengauss数据库具有TEMPORARY,CONNECT,CREATE,TEMPORARY,CONNECT等权限
根据用户名查询table 权限,可以通过视图information_schema.table_privileges来查看,为了方便展示,sql如下

--寄语--
OSPP: 对想要参与以及还未参与开源的同学鼓励一下吧! 陈贤文: 开源项目就在那里,总有一些新的需求和方向可以为之贡献自己的力量,当我们就有了一定的技术能力和知识储备,了解和掌握开源工具、语言和框架了之后,就一起来加入开源社区吧!找到合适的开源项目之后,勇敢和导师与社区开发者交流,参与进来,一起分享自己的知识和经验,帮助他人解决问题,一起学习与成长!相关文章:
项目经验分享|openGauss 陈贤文:受益于开源,回馈于开源
开源之夏 项目经验分享 2023 #08 # 关于 openGauss 社区 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合华为在数据库领域多年的经验,结合企业级场景需求,持续构建竞争力特性。同时openGauss也是…...
实时检测并识别视频中的汽车车牌
对于基于摄像头监控的安全系统来说,识别汽车牌照是一项非常重要的任务。我们可以使用一些计算机视觉技术从图像中提取车牌,然后我们可以使用光学字符识别来识别车牌号码。在这里,我将引导您完成此任务的整个过程。 要求: import cv2import numpy as npfrom skimage impor…...
使用 pyspark 进行 Clustering 的简单例子 -- KMeans
K-means算法适合于简单的聚类问题,但可能不适用于复杂的聚类问题。此外,在使用K-means算法之前,需要对数据进行预处理和缩放,以避免偏差。 K-means是一种聚类算法,它将数据点分为不同的簇或组。Pyspark实现的K-means算法基本遵循以下步骤: 随机选择K个点作为初始质心。根…...
LeetCode75——Day22
文章目录 一、题目二、题解 一、题目 1657. Determine if Two Strings Are Close Two strings are considered close if you can attain one from the other using the following operations: Operation 1: Swap any two existing characters. For example, abcde -> aec…...
【SOC基础】单片机学习案例汇总 Part1:电机驱动、点亮LED
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
【HTML】HTML基础知识扫盲
1、什么是HTML? HTML是超文本标记语言(Hyper Text Markup Language)是用来描述网页的一种语言 注意: HTML不是编程语言,而是标记语言 HTML文件也可以直接称为网页,浏览器的作用就是读取HTML文件ÿ…...
【Mybatis-Plus】常见的@table类注解
目录 引入Mybatis-Plus依赖 TableName 当实体类的类名在转成小写后和数据库表名相同时 当实体类的类名在转成小写后和数据库表名不相同时 Tableld TableField 当数据库字段名与实体类成员不一致 成员变量名以is开头,且是布尔值 编辑 成员变量名与数据库关…...
Android WMS——操作View(七)
上一篇文章我们将 view 传递给 ViewRootImpl 进行操作,这里我们主要分析 ViewRootImpl 对 View 进行操作。在正式分析之前我们先来介绍以下 View。 一、View介绍 最开始学习 View 的时候最先分析的是它的布局(LinearLayout、FrameLayout、TableLayout、RelativeLayout、Abso…...
算法__数组排序_冒泡排序直接选择排序快速排序
文章目录 冒泡排序算法说明代码实现 直接选择排序算法说明代码实现 快速排序算法说明代码实现 本篇主要讲解数组排序相关的三种算法,冒泡排序,直接排序和快速排序。 冒泡排序 算法说明 在数组中依次比较相邻的两个元素,当满足左侧大于右侧时…...
ByteBuffer的原理和使用详解
ByteBuffer是字节缓冲区,主要用户读取和缓存字节数据,多用于网络编程,原生的类,存在不好用,Netty采用自己的ByteBuff,对其进行了改进 1.ByteBuffer的2种创建方式 1.ByteBuffer buf ByteBuffer.allocate(i…...
【MySql】10- 实践篇(八)
文章目录 1. 用动态的观点看加锁1.1 不等号条件里的等值查询1.2 等值查询的过程1.3 怎么看死锁?1.4 怎么看锁等待?1.5 update 的例子 2. 误删数据后怎么办?2.1 删除行2.2 误删库/表2.3 延迟复制备库2.4 预防误删库 / 表的方法2.4.1 账号分离2.4.2 制定操…...
【三方登录-Apple】iOS 苹果授权登录(sign in with Apple)之开发者配置一
记录一下sign in with Apple的开发者配置 前言 关于使用 Apple 登录 使用“通过 Apple 登录”可让用户设置帐户并使用其Apple ID登录您的应用程序和关联网站。首先使用“使用 Apple 登录”功能启用应用程序的App ID 。 如果您是首次启用应用程序 ID 或为新应用程序启用应用程序…...
可视化 | 数据可视化降维算法梳理
文章目录 📚数据描述🐇iris🐇MNIST 📚PCA🐇算法流程🐇图像描述 📚Kernel-PCA🐇算法流程🐇图像描述 📚MDS🐇算法流程🐇图像描述 &#…...
分布式:一文吃透分布式事务和seata事务
目录 一、事务基础概念二、分布式事务概念什么是分布式事务分布式事务场景CAP定理CAP理论理解CAPCAP的应用 BASE定理强一致性和最终一致性BASE理论 分布式事务分类刚性事务柔性事务 三、分布式事务解决方案方案汇总XA规范方案1:2PC第一阶段:准备阶段第二…...
Java架构师前沿技术
目录 1 导学2 信息物理系统2.1CPS的体系架构2.2 CPS的技术体系3 人工智能4 机器人5 边缘计算6 数字李生体7 云计算7.1 云计算的部署模式8 大数据想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导学 2 信息物理系统 信息物理系统(CPS)是控制系统、嵌入式系统的扩展与…...
OpenCV ycrcb颜色空间
Opencv中有一个Ycrcb的选项,这个选项其实是Yuv444packet. 下面代码从文件中获取到一个yuv444planar的文件,通过手动转换,将其转为YcrCb,然后进行颜色空间csc. 所以可以确定这是一个packet的存储格式 def yuv444p_2_bgr8_opencv(…...
SPSS两独立样本t检验
前言: 本专栏参考教材为《SPSS22.0从入门到精通》,由于软件版本原因,部分内容有所改变,为适应软件版本的变化,特此创作此专栏便于大家学习。本专栏使用软件为:SPSS25.0 本专栏所有的数据文件请点击此链接下…...
视频格式高效转换:MP4视频批量转MKV格式的方法
随着数字媒体技术的不断发展,视频格式转换已经成为了我们日常工作中不可或缺的一部分。不同的视频格式适用于不同的场景和设备,因此将视频从一种格式转换为另一种格式往往是我们必须完成的任务。在本文中,我们将重点介绍如何运用云炫AI智剪高…...
0028Java程序设计-智能农场监控报警系统设计与实现
文章目录 摘要目 录系统设计开发环境 摘要 我国是一个以农业为主的国家,在当今社会信息化迅速发展的背景下,将信息技术与农业相融合是必然的趋势。现代信息技术在农业生产中的运用,主要体现在两个领域:一是传感器技术;…...
数据结构和算法——用C语言实现所有图状结构及相关算法
文章目录 前言图的基本概念图的存储方式邻接矩阵邻接表十字链表临界多重表 图的遍历最小生成树普里姆算法(Prim)克鲁斯卡尔算法(Kruskal) 最短路径BFS求最短路径迪杰斯特拉算法(Dijkstra)弗洛伊德算法&…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
