数据库平滑switchover的要素 - 会话资源漂移

标签

PostgreSQL , 中间件 , 连接池 , 平滑切换 , 会话设置 , 会话状态 , 绑定变量语句 , prepared statement


背景

数据库迁移、切换是很普遍的一个话题,但是大多数的方案,对用户来说都是有感知的,所以用户的体验并不好。

例如用户使用了绑定变量语句,主备角色切换后绑定变量语句没有了,会导致调用报错。

我们需要维护主库的硬件,那么可以在中间件层面,将主备数据库的角色进行平滑调换,维护好硬件,再平滑的调换回来。

数据库主备切换时,如何做到会话级无感知?首先我们要了解会话中都有哪些内容,哪些内容是需要随角色切换一起迁移的。从而做到用户无感知。

(本文HA指中间件层级的HA,并非APP直连数据库,VIP切换的那种HA。)

简单的switchover过程举例:

等待所有会话的事务结束,会话都处于idle状态,冻结会话,不允许提交任何SQL,然后进行角色切换,并将每个会话的资源状态平移。

会话资源状态

会话中有些什么状态?通过discard这条SQL就可以了解。

https://www.postgresql.org/docs/10/static/sql-discard.html

DISCARD — discard session state

discard all相当于执行如下

SET SESSION AUTHORIZATION DEFAULT;
RESET ALL;
DEALLOCATE ALL;
CLOSE ALL;
UNLISTEN *;
SELECT pg_advisory_unlock_all();
DISCARD PLANS;
DISCARD SEQUENCES;
DISCARD TEMP;

会话资源中目前可能包含如下(每个PG版本可能有些许差异):

SESSOIN角色、参数设置、绑定变量语句、游标、异步消息监听、AD锁、序列、临时表等。

下面介绍一下每种资源的查询方法,以及在新的主库上进行资源复原的方法。

一、SESSION AUTHORIZATION

超级用户可以将会话用户设置为其他用户,普通用户无权切换用户。

当前用户为postgres,设置SESSION AUTHORIZATION为test

postgres=# set SESSION AUTHORIZATION test;
SET
postgres=> show SESSION AUTHORIZATION;
 session_authorization
-----------------------
 test
(1 row)
postgres=> select usename from pg_stat_activity where pid=pg_backend_pid();
 usename
----------
 postgres
(1 row)

查询方法

postgres=> show SESSION AUTHORIZATION;
 session_authorization
-----------------------
 test
(1 row)
postgres=> select usename from pg_stat_activity where pid=pg_backend_pid();
 usename
----------
 postgres
(1 row)

复原方法

当pg_stat_activity.usename不等于SESSION AUTHORIZATION时,需要通过如下方法复原它。

postgres=# set SESSION AUTHORIZATION test;
SET

二、参数

PostgreSQL的一些参数是允许用户在会话、事务中进行设置的。如下context in ('user','superuser')时,用户可以在会话或事务中设置。

postgres=# select distinct context from pg_settings ;
      context
-------------------
 superuser-backend
 sighup
 superuser
 postmaster
 internal
 user
 backend
(7 rows)

设置例子

postgres=> set tcp_keepalives_count=1;
SET  

source表示参数来自哪里的设置,如果来自会话或事务级设置,则显示session  

postgres=> select distinct source from pg_settings ;
        source
----------------------
 session
 default
 command line
 configuration file
 client
 override
 environment variable
(7 rows)  

重置方法  

postgres=# reset tcp_keepalives_count;
RESET
postgres=# select name,setting,reset_val,source,context from pg_settings where name='tcp_keepalives_count';
         name         | setting | reset_val | source  | context
----------------------+---------+-----------+---------+---------
 tcp_keepalives_count | 3       | 0         | default | user
(1 row)

查询方法

postgres=# select name,setting,reset_val,source,context from pg_settings where source ='session' and setting<>reset_val;
         name         | setting | reset_val | source  | context
----------------------+---------+-----------+---------+---------
 tcp_keepalives_count | 1       | 0         | session | user
(1 row)

复原方法

postgres=> set tcp_keepalives_count=1;
SET

三、绑定变量语句

使用绑定变量可以减少数据库的parser, plan开销,提高高并发的查询性能,同时避免SQL注入。

不同的驱动,有不同的使用方法。

https://www.postgresql.org/docs/10/static/libpq-exec.html#libpq-exec-main

使用绑定变量的例子

CREATE OR REPLACE FUNCTION public.getps()
 RETURNS void
 LANGUAGE plpgsql
 STRICT
AS $function$
declare
  rec record;
begin
  for rec in select t from pg_prepared_statements t loop
    raise notice '%', (rec.*)::text;
  end loop;
end;
$function$;  

create table ps(id int primary key, info text);
insert into ps select generate_series(1,10000), 'test';  

vi test.sql  

\set id random(1,10000)
select * from ps where id=:id;
select getps();  

使用绑定变量的模式,调用SQL  

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 1 -j 1  

NOTICE:  ("(P0_1,""select * from ps where id=$1;"",""2017-06-19 15:22:21.821454+08"",{integer},f)")
NOTICE:  ("(P0_2,""select getps();"",""2017-06-19 15:22:21.822045+08"",{},f)")
.....

查询方法

postgres=# \d pg_prepared_statements
                  View "pg_catalog.pg_prepared_statements"
     Column      |           Type           | Collation | Nullable | Default
-----------------+--------------------------+-----------+----------+---------
 name            | text                     |           |          |
 statement       | text                     |           |          |
 prepare_time    | timestamp with time zone |           |          |
 parameter_types | regtype[]                |           |          |
 from_sql        | boolean                  |           |          |   

postgres=# select * from pg_prepared_statements;
 name | statement | prepare_time | parameter_types | from_sql
------+-----------+--------------+-----------------+----------
(0 rows)  

postgres=# prepare a(int) as select * from ps where id=$1;
PREPARE
postgres=# execute a(1);
 id | info
----+------
  1 | test
(1 row)  

postgres=# select * from pg_prepared_statements;
 name |                    statement                    |         prepare_time         | parameter_types | from_sql
------+-------------------------------------------------+------------------------------+-----------------+----------
 a    | prepare a(int) as select * from ps where id=$1; | 2017-06-19 15:23:24.68617+08 | {integer}       | t
(1 row)

复原方法

不同的驱动,复原方法不一样。

请根据pg_prepared_statements的内容进行复原。

NOTICE:  ("(P0_1,""select * from ps where id=$1;"",""2017-06-19 15:22:21.821454+08"",{integer},f)")  

PGresult *PQprepare(PGconn *conn,
                    const char *stmtName,
                    const char *query,
                    int nParams,
                    const Oid *paramTypes);

四、游标

如果我们使用了hold选项,那么游标不会随事务结束而关闭,因此在迁移会话时也需要注意是否有这类游标。

postgres=# \h declare
Command:     DECLARE
Description: define a cursor
Syntax:
DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ]
    CURSOR [ { WITH | WITHOUT } HOLD ] FOR query  

postgres=# begin;
BEGIN
postgres=# declare cur cursor with hold for select * from ps where id=1;
DECLARE CURSOR
postgres=# end;
COMMIT
postgres=# select * from pg_cursors ;
 name |                           statement                           | is_holdable | is_binary | is_scrollable |         creation_time
------+---------------------------------------------------------------+-------------+-----------+---------------+-------------------------------
 cur  | declare cur cursor with hold for select * from ps where id=1; | t           | f         | t             | 2017-06-19 15:27:58.604183+08
(1 row)  

postgres=# close cur;
CLOSE CURSOR
postgres=# select * from pg_cursors ;
 name | statement | is_holdable | is_binary | is_scrollable | creation_time
------+-----------+-------------+-----------+---------------+---------------
(0 rows)  

查询方法

postgres=# select * from pg_cursors ;
 name |                           statement                           | is_holdable | is_binary | is_scrollable |         creation_time
------+---------------------------------------------------------------+-------------+-----------+---------------+-------------------------------
 cur  | declare cur cursor with hold for select * from ps where id=1; | t           | f         | t             | 2017-06-19 15:27:58.604183+08
(1 row)

复原方法

postgres=# declare cur cursor with hold for select * from ps where id=1;
DECLARE CURSOR

五、异步消息监听

PostgreSQL的异步消息,可以通过异步消息,推送事件。例子如下:

https://www.postgresql.org/docs/10/static/libpq-notify.html

https://www.postgresql.org/docs/10/static/libpq-example.html#libpq-example-2

postgres=# listen a;
LISTEN
postgres=# notify a , 'hello i am digoal';
NOTIFY
Asynchronous notification "a" with payload "hello i am digoal" received from server process with PID 21412.

查询方法

查询已经开启了哪些异步监听

postgres=# select pg_listening_channels();
 pg_listening_channels
-----------------------
 a
(1 row)

复原方法

postgres=# listen a;
LISTEN

六、advisory lock

advisory lock可以用于秒杀、解决高并发锁冲突问题、解决无空洞序列值问题等。

《PostgreSQL 使用advisory lock实现行级读写堵塞》

《PostgreSQL 无缝自增ID的实现 - by advisory lock》

《PostgreSQL 使用advisory lock或skip locked消除行锁冲突, 提高几十倍并发更新效率》

《聊一聊双十一背后的技术 - 不一样的秒杀技术, 裸秒》

postgres=# \df *.*advis*
                                        List of functions
   Schema   |               Name               | Result data type | Argument data types |  Type
------------+----------------------------------+------------------+---------------------+--------
 pg_catalog | pg_advisory_lock                 | void             | bigint              | normal
 pg_catalog | pg_advisory_lock                 | void             | integer, integer    | normal
 pg_catalog | pg_advisory_lock_shared          | void             | bigint              | normal
 pg_catalog | pg_advisory_lock_shared          | void             | integer, integer    | normal
 pg_catalog | pg_advisory_unlock               | boolean          | bigint              | normal
 pg_catalog | pg_advisory_unlock               | boolean          | integer, integer    | normal
 pg_catalog | pg_advisory_unlock_all           | void             |                     | normal
 pg_catalog | pg_advisory_unlock_shared        | boolean          | bigint              | normal
 pg_catalog | pg_advisory_unlock_shared        | boolean          | integer, integer    | normal
 pg_catalog | pg_advisory_xact_lock            | void             | bigint              | normal
 pg_catalog | pg_advisory_xact_lock            | void             | integer, integer    | normal
 pg_catalog | pg_advisory_xact_lock_shared     | void             | bigint              | normal
 pg_catalog | pg_advisory_xact_lock_shared     | void             | integer, integer    | normal
 pg_catalog | pg_try_advisory_lock             | boolean          | bigint              | normal
 pg_catalog | pg_try_advisory_lock             | boolean          | integer, integer    | normal
 pg_catalog | pg_try_advisory_lock_shared      | boolean          | bigint              | normal
 pg_catalog | pg_try_advisory_lock_shared      | boolean          | integer, integer    | normal
 pg_catalog | pg_try_advisory_xact_lock        | boolean          | bigint              | normal
 pg_catalog | pg_try_advisory_xact_lock        | boolean          | integer, integer    | normal
 pg_catalog | pg_try_advisory_xact_lock_shared | boolean          | bigint              | normal
 pg_catalog | pg_try_advisory_xact_lock_shared | boolean          | integer, integer    | normal
(21 rows)

advisory lock分为事务级锁和会话级锁,在会话迁移时,会话处于IDLE状态, 只需要关注会话级锁。

postgres=# select pg_try_advisory_lock(1);
 pg_try_advisory_lock
----------------------
 t
(1 row)

查询方法

postgres=# select * from pg_locks where locktype='advisory' and pid=pg_backend_pid();
 locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction |  pid  |     mode      | granted | fastpath
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-------+---------------+---------+----------
 advisory |    13158 |          |      |       |            |               |       0 |     1 |        1 | 3/123301864        | 21412 | ExclusiveLock | t       | f
(1 row)

复原方法

注意复原时,需要指定是否为shared lock。

postgres=# select pg_try_advisory_lock(1);
 pg_try_advisory_lock
----------------------
 t
(1 row)

七、序列

序列使用后,会在会话中存储最后一次使用的序列的VAL,以及每个序列被使用后的最后一次获取的VAL。

postgres=# create sequence seq1;
CREATE SEQUENCE  

没有被调用的序列,返回错误。
postgres=# select currval('seq');
ERROR:  currval of sequence "seq" is not yet defined in this session  

没有调用过任何序列,返回错误。
postgres=# select lastval();
ERROR:  lastval is not yet defined in this session  

调用序列
postgres=# select nextval('seq1');
 nextval
---------
       1
(1 row)  

返回会话中指定序列最后一次调用的VAL
postgres=# select currval('seq1');
 currval
---------
       1
(1 row)  

返回整个会话中最后一次序列调用的VAL
postgres=# select lastval();
 lastval
---------
       1
(1 row)

查询方法

postgres=# select * from seq1;
 last_value | log_cnt | is_called
------------+---------+-----------
          1 |      32 | t
(1 row)
postgres=# select nextval('seq1');
 nextval
---------
       2
(1 row)  

postgres=# select * from seq1;
 last_value | log_cnt | is_called
------------+---------+-----------
          2 |      31 | t
(1 row)

复原方法

序列虽然可以设置当前值,但是会影响全局,强烈建议不要这么做。

目前没有好的方法复原序列在会话中的lastval。

八、临时表

postgres=# create temp table tmp(id int, info text);
CREATE TABLE  

postgres=# select oid,relname from pg_class where relpersistence ='t' and relkind='r' and pg_table_is_visible(oid);
  oid  | relname
-------+---------
 44804 | tmp
(1 row)

查询方法

postgres=# select oid,relname from pg_class where relpersistence ='t' and relkind='r' and pg_table_is_visible(oid);
  oid  | relname
-------+---------
 44804 | tmp
(1 row)  

********* QUERY **********
SELECT c.oid,
  n.nspname,
  c.relname
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ~ '^(tmp)$'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2, 3;
**************************  

********* QUERY **********
SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, c.relhasoids, pg_catalog.array_to_string(c.reloptions || array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')
, c.reltablespace, CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, c.relpersistence, c.relreplident
FROM pg_catalog.pg_class c
 LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
WHERE c.oid = '44810';
**************************  

********* QUERY **********
SELECT a.attname,
  pg_catalog.format_type(a.atttypid, a.atttypmod),
  (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
   FROM pg_catalog.pg_attrdef d
   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),
  a.attnotnull, a.attnum,
  (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t
   WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation, a.attidentity,
  NULL AS indexdef,
  NULL AS attfdwoptions,
  a.attstorage,
  CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget, pg_catalog.col_description(a.attrelid, a.attnum)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = '44810' AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;
**************************  

********* QUERY **********
SELECT inhparent::pg_catalog.regclass,          pg_get_expr(c.relpartbound, inhrelid),          pg_get_partition_constraintdef(inhrelid) FROM pg_catalog.pg_class c JOIN pg_catalog.pg_inherits ON c.oid = inhrelid WHERE c.oid = '44810' AND c.relispartition;
**************************  

********* QUERY **********
SELECT pol.polname, pol.polpermissive,
CASE WHEN pol.polroles = '{0}' THEN NULL ELSE array_to_string(array(select rolname from pg_roles where oid = any (pol.polroles) order by 1),',') END,
pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),
pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),
CASE pol.polcmd
WHEN 'r' THEN 'SELECT'
WHEN 'a' THEN 'INSERT'
WHEN 'w' THEN 'UPDATE'
WHEN 'd' THEN 'DELETE'
END AS cmd
FROM pg_catalog.pg_policy pol
WHERE pol.polrelid = '44810' ORDER BY 1;
**************************  

********* QUERY **********
SELECT oid, stxrelid::pg_catalog.regclass, stxnamespace::pg_catalog.regnamespace AS nsp, stxname,
  (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')
   FROM pg_catalog.unnest(stxkeys) s(attnum)
   JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND
        a.attnum = s.attnum AND NOT attisdropped)) AS columns,
  (stxkind @> '{d}') AS ndist_enabled,
  (stxkind @> '{f}') AS deps_enabled
FROM pg_catalog.pg_statistic_ext stat WHERE stxrelid = '44810'
ORDER BY 1;
**************************  

********* QUERY **********
SELECT pub.pubname
 FROM pg_catalog.pg_publication pub
 LEFT JOIN pg_catalog.pg_publication_rel pr
      ON (pr.prpubid = pub.oid)
WHERE pr.prrelid = '44810' OR pub.puballtables
ORDER BY 1;
**************************  

********* QUERY **********
SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '44810' AND c.relkind != 'p' ORDER BY inhseqno;
**************************  

********* QUERY **********
SELECT c.oid::pg_catalog.regclass, pg_get_expr(c.relpartbound, c.oid) FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhrelid AND i.inhparent = '44810' AND EXISTS (SELECT 1 FROM pg_class c WHERE c.oid = '44810') ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;
**************************  

                                   Table "pg_temp_3.tmp"
 Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description
--------+---------+-----------+----------+---------+----------+--------------+-------------
 id     | integer |           |          |         | plain    |              |
 info   | text    |           |          |         | extended |              |

复原方法

postgres=# create temp table tmp(id int, info text);
CREATE TABLE

小结

主备切换时,将会话资源状态进行平移,可以大幅提升客户端的体验,使得数据库硬件维护、迁移等工作也会变得更加轻松。

中间件需要维护客户端连接和数据库会话的映射关系,平移后映射关系同样需要保持一致。

参考

https://www.postgresql.org/docs/10/static/libpq-exec.html#libpq-exec-main

https://www.postgresql.org/docs/10/static/sql-discard.html

时间: 2024-10-26 15:00:56

数据库平滑switchover的要素 - 会话资源漂移的相关文章

mysql转mariadb数据库平滑过渡例子

一,mariadb与mysql 1,mariadb简介 MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL AB卖给了SUN,此后,随着SUN被甲骨文收购,MySQL的所有权也落入Oracle的手中.MariaDB名称来自Michael Widenius的女儿Maria的名字. 2,mariadb产生的原因 MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在

数据库案例集锦 - 开发者的《如来神掌》

背景 「剑魔独孤求败,纵横江湖三十馀载,杀尽仇寇,败尽英雄,天下更无抗手,无可柰何,惟隐居深谷,以雕为友.呜呼,生平求一敌手而不可得,诚寂寥难堪也.」 剑冢中,埋的是剑魔独孤求败毕生几个阶段中用过的几柄剑: 利剑无意:第一柄是青光闪闪的利剑,凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋. 软剑无常:第二柄是紫薇软剑,三十岁前所用,误伤义士不祥,悔恨不已,乃弃之深谷. 重剑无锋:第三柄是玄铁重剑,重剑无锋,大巧不工,四十岁之前恃之横行天下. 木剑无俦:第四柄是已腐朽的木剑. 无剑无招:四十岁后,不

阿里云RDS金融数据库(三节点版) - 案例篇

标签 PostgreSQL , MySQL , 三节点版 , 金融数据库 , Raft , 分布式共享存储版 背景 土豆哪里去挖? 土豆郊区去挖. 一挖一麻袋? 一挖一麻袋. 挖掘机不仅是城市建设的必备法宝,居然也是挖土豆利器. 但是科技行业一定不喜欢挖掘机,经常会听说xx互联网软件故障提到"光纤被挖断",导致XX机房故障几小时. 这和数据库有什么关系呢?当然有,一些企业在业务层面可能做到了多机房,多活的架构,但数据库并没有做到0丢失的多机房或多活部署,如果数据库所在机房网络故障,那么

浅谈数据库资源使用的按需分配方法

SQL Server资源调节器的作用 如果有5个业务都很繁忙的数据库需要部署在一台服务器上,为了避免相互的资源抢占,我们通常会在服务器上安装5个SQL Server实例来分别承载这5个数据库,然后分别设置每个实例的最大和最小内存.CPU掩码等,用以s控制这5个业务数据库的资源分配. 笔者的公司曾经就有这样的案例.这种方式的缺点显而易见:首先是授权,在上述例子中,5个SQL Server实例的费用应该是比1个要高:其次是管理成本提高,DBA不得不安装和维护5个实例.那么,有没有更好的方法呢? 其实

《Oracle数据库性能优化方法论和最佳实践》——1.5 测量和变化

1.5 测量和变化 1.5.1 测量和性能 没有测量就没有性能,任何科学都建立在可测量的基础之上.Oracle数据库和基于它的性能优化理所当然是一门科学,而不是一门艺术.科学的性能优化首先必须是可以建立测量的目标系统性能指标.一个无法测量的系统或者一个只能依赖于人的眼睛.耳朵等器官来进行感知的系统是无法进行性能优化的.为了完成性能优化,需要做大量的可测量性工作.幸运的是,Oracle对于可测量的性能付出了巨大的努力,使其性能相关的测量指标远远超出了其他数据库. 从性能优化的角度出发,可以从以下几

如何优化Urchin配置文件数据库的磁盘空间

Urchin 的报告数据存储在各个配置文件所独有的每月数据库中(注:Urchin分析后的数据是按月归档),这些数据库一般位于 Urchin 的 data/reports 目录下.每个配置经过处理的数据库大小为原日志大小的5% 至10%. 默认情况下,Urchin 会保留每月的这些配置文件数据库,但经过长时间的数据积累数据量会变大,导致Urchin处理后的数据占用空间越来越大,并且在用户查看时也会降低Urchin的响应效率.因此,需要优化Urchin 配置文件每月数据库的磁盘存储空间. 优化 Ur

Oracle数据库几种关闭方式

oracle|数据|数据库 1.shutdown normal 正常方式关闭数据库. 2.shutdown immediate 立即方式关闭数据库. 在SVRMGRL中执行shutdown immediate,数据库并不立即关闭, 而是在Oracle执行某些清除工作后才关闭(终止会话.释放会话资源), 当使用shutdown不能关闭数据库时,shutdown immediate可以完成数据库关闭的操作. 3.shutdown abort 直接关闭数据库,正在访问数据库的会话会被突然终止, 如果数

Oracle数据库的启动和关闭方式小结

oracle|数据|数据库 Oracle数据库的启动和关闭方式 一.几种启动方式: 1.startup nomount     非安装启动,这种方式启动下可执行:重建控制文件.重建数据库     启动instance,即启动SGA和后台进程,这种启动只需要init.ora文件.  2.startup mount dbname     安装启动,这种方式启动下可执行:数据库日志归档.数据库恢复.重新命名一些数据库文件     如:系统表空间或日志文件.     执行"nomount",然

Oracle管理安全和资源(三)Oracle资源管理器简介

Oracle资源管理器(Oracle Database Resource Manager,以下简称DBRM)管理数据库资源,为不同的会话分配不同的数据库资源.DBRM管理的资源主要包括CPU时间.下面分以下几个章节介绍: Oracle DBRM帮你处理哪些问题 Oracle DBRM是怎样处理这些问题的 Oracle DBRM包含的内容 Oracle DBRM资源分配方法 Oracle DBRM的权限管理 1.Oracle DBRM帮你处理哪些问题  当数据库服务器资源由操作系统来分配时,你可能