Edition-Based Redefinition
Oracle在11g引入了Edition-Based Redefinition(EBR),主要是为了解决在更新数据库对象,比如PL/SQL程序,视图等,如果该对象被锁住了,会导致更新必须等待,如果要使更新立即完成,则需要停止应用的问题。实现方式就是通过创建版本,新的代码在子版本实现,通过指定版本来对新旧版本代码进行切换。
这个功能主要用在有大量PL/SQL程序的数据库,例如Oracle EBS数据库。
EBR通过版本化的方式可实现以下目标:
代码的改变,包括PL/SQL,表定义等,安装在子(新)版本中
数据的改变只写到新的表或新的列,父(老)版本不会看到
跨版本触发器将父(老)版本应用所做改变反映到子(新)版本中,反之亦然
EBR依赖于3类新的对象,即edition、editioning view和crossedition trigger。
若只改变视图,同义词和PL/SQL对象,edition就够了
若表结构和数据的改变并是在后端完成,不涉及终端用户,则只需edition和editioning view
若表结构和数据的改变是由终端用户发起,则三者都需要
Edition
版本化和非版本化对象
Edition是非Schema对象,不属于任何用户,从11gR2开始,每个数据库都有一个默认版本,即ORA$BASE。
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL> SELECT SYS_CONTEXT('userenv', 'current_edition_name') from dual;
SYS_CONTEXT('USERENV','CURRENT_EDITION_NAME')
--------------------------------------------------------------------------------
ORA$BASE
SQL> select edition_name,parent_edition_name,usable from dba_editions;
EDITION_NAME PARENT_EDITION_NAME USA
------------------------------ ------------------------------ ---
ORA$BASE YES
可版本化对象
不是所有的模式对象都是可版本化(editionable )的,可版本化的模式对象有:
SYNONYM
VIEW
- All PL/SQL object types:
FUNCTION
LIBRARY
PACKAGE
andPACKAGE BODY
PROCEDURE
TRIGGER
TYPE
andTYPE BODY
除此之外,其他对象,例如表,公有同义词,都是不支持版本化的。
如果可版本化对象的所有者是editions-enabled ,则该对象是editioned ,否则该对象是potentially editioned。
版本化对象规则
A noneditioned object cannot depend on an editioned object.
For example:
- A public synonym cannot refer to an editioned object.
- A function-based index cannot depend on an editioned function.
- A materialized view cannot depend on an editioned view.
- A table cannot have a column of a user-defined data type (collection or Abstract Data Type (ADT)) whose owner is editions-enabled.
- A noneditioned subprogram cannot have a static reference to a subprogram whose owner is editions-enabled.
For the reason for this rule, see "Actualizing Referenced Objects".
An ADT cannot be both editioned and evolved.
For information about type evolution, see Oracle Database Object-Relational Developer's Guide.
An editioned object cannot be the starting or ending point of a
FOREIGN KEY
constraint.The only editioned object that this rule affects is an editioned view. An editioned view can be either an ordinary view or an editioning view.
用户启用版本
可以在CREATE USER
或者ALTER USER
语句中使用使用ENABLE EDITIONS
语句来为用户启用版本。该操作是不可逆的,一旦为用户启用版本,则该用户现有可版本化对象及后续创建的可版本化对象就自动版本化了。
如果启用版本的两个用户之间存在相关的依赖关系,还需要使用FORCE
关键字先为某一个用户启用版本。例如用户A有可版本化的对象a1和a2,用户B有可版本的对象b1和b2,对象a1依赖对象b1,对象b2依赖对象a2,则为用户A和用户B启用版本步骤如下:
Using
FORCE
, enable editions for userA
:ALTER USER A ENABLE EDITIONS FORCE;
Now
a1
anda2
are editioned objects, andb2
(which depends ona2
) is invalid.Enable editions for user
B
:ALTER USER B ENABLE EDITIONS;
Recompile
b2
, using the appropriateALTER
statement withCOMPILE
. For a PL/SQL object, also specifyREUSE
SETTINGS
.For example, if
b2
is a procedure, use this statement:ALTER PROCEDURE b2 COMPILE REUSE SETTINGS
创建版本
使用CREATE EDITION
语句来创建版本。
继承对象和实际对象
每个数据库会话一次只能使用一个版本。创建时,子版本从其父版本继承数据库中在父版本中可见的所有已版本化对象。每个继承的对象在子版本中可见。
例子: creates a procedure named hello
in the edition ora$base
, and then creates the edition e2
as a child of ora$base
. When e2
invokes hello
, it invokes the inherited procedure. Then e2
changes hello
, actualizing it. The procedure hello
in the edition ora$base
remains unchanged, and is no longer visible in e2
. Now when e2
invokes hello
, it invokes the actual procedure.
先创建用户,授予权限,启用版本,切换到新创建的用户
SQL> create user user1 identified by user1 default tablespace users;
User created.
SQL> grant dba to user1;
Grant succeeded.
SQL> alter user user1 enable editions;
User altered.
SQL> conn user1/user1
Connected.
再执行如下步骤:
Create procedure in parent edition:
CREATE OR REPLACE PROCEDURE hello IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, edition 1.');
END hello;
/
Invoke procedure in parent edition:
BEGIN hello(); END;
/
Result:
Hello, edition 1. PL/SQL procedure successfully completed.
Create child edition:
CREATE EDITION e2;
Use child edition:
ALTER SESSION SET EDITION = e2;
For information about
ALTER
SESSION
SET
EDITION
, see "Changing Your Session Edition".In child edition, invoke procedure:
BEGIN hello(); END;
/
Child edition inherits procedure from parent edition. Child edition invokes inherited procedure. Result:
Hello, edition 1. PL/SQL procedure successfully completed.
Change procedure in child edition:
CREATE OR REPLACE PROCEDURE hello IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, edition 2.');
END hello;
/
Child changes only its own copy of procedure. Child's copy is an actual object.
Invoke procedure:
BEGIN hello(); END;
/
Child invokes its own copy, the actual procedure:
Hello, edition 2. PL/SQL procedure successfully completed.
Return to parent:
ALTER SESSION SET EDITION = ora$base;
Invoke procedure and see that it has not changed:
BEGIN hello(); END;
/
Result:
Hello, edition 1. PL/SQL procedure successfully completed.
删除继承对象
如果子版本的用户删除继承对象,则该对象在子版本中不再可见,但在父版本中仍然可见。
例子: creates a procedure named goodbye
in the edition ora$base
, and then creates edition e2
as a child of ora$base
. After e2
drops goodbye
, it can no longer invoke it, but ora$base
can still invoke it.
先删除之前创建的版本:
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL> drop edition e2 cascade;
Edition dropped.
再执行以下步骤:
Create procedure in edition
ora$base
:CREATE OR REPLACE PROCEDURE goodbye IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Good-bye!');
END goodbye;
/
Invoke procedure:
BEGIN goodbye; END;
/
Result:
Good-bye! PL/SQL procedure successfully completed.
Create edition
e2
as a child ofora$base
:CREATE EDITION e2;
Use edition
e2
:ALTER SESSION SET EDITION = e2;
ALTER
SESSION
SET
EDITION
must be a top-level SQL statement. For more information, see "Changing Your Session Edition".In
e2
, invoke procedure:BEGIN goodbye; END;
/
e2
invokes inherited procedure:Good-bye! PL/SQL procedure successfully completed.
In
e2
, drop procedure:DROP PROCEDURE goodbye;
In
e2
, try to invoke dropped procedure:BEGIN goodbye; END;
/
Result:
BEGIN goodbye; END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'GOODBYE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Return to parent:
ALTER SESSION SET EDITION = ora$base;
In parent, invoke procedure:
BEGIN goodbye; END;
/
Result:
Good-bye! PL/SQL procedure successfully completed.
例子: e2
creates a function named goodbye
and then an edition named e3
as a child of e2
. When e3
tries to invoke the procedure goodbye
(which e2
dropped), an error occurs, but e3
successfully invokes the function goodbye
(which e2
created).
Return to
e2
:ALTER SESSION SET EDITION = e2;
For information about
ALTER
SESSION
SET
EDITION
, see "Changing Your Session Edition".In
e2
, create function namedgoodbye
:CREATE OR REPLACE FUNCTION goodbye
RETURN BOOLEAN
IS
BEGIN
RETURN(TRUE);
END goodbye;
/
Create edition
e3
:CREATE EDITION e3 AS CHILD OF e2;
Use edition
e3
:ALTER SESSION SET EDITION = e3;
In
e3
, try to invoke proceduregoodbye
:BEGIN
goodbye;
END;
/
Result:
goodbye;
*
ERROR at line 2:
ORA-06550: line 2, column 3:
PLS-00221: 'GOODBYE' is not a procedure or is undefined
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
In
e3
, invoke functiongoodbye
:BEGIN
IF goodbye THEN
DBMS_OUTPUT.PUT_LINE('Good-bye!');
END IF;
END;
/
Result:
Good-bye! PL/SQL procedure successfully completed.
版本授权
版本创建者可以使用语句 GRANT
USE
ON
EDITION
将版本的使用权限授予其他用户。
如果要授予所有用户,则可以使用以下两种方式:
Grant the
USE
privilege on the edition toPUBLIC
:GRANT USE ON EDITION edition_name TO PUBLIC
Make the edition the database default edition:
ALTER DATABASE DEFAULT EDITION = edition_name
This has the side effect of granting the
USE
privilege onedition_name
toPUBLIC
.
当前版本和会话版本
数据库会话在任何时间使用的版本为当前版本(current edition),当数据库会话开始,当前版本就是其会话版本(session edition),改变会话版本,当前版本也会随之改变。但是,也会有当前版本与会话版本不同的情况。
初始会话版本
当连接数据库时,可以指定初始会话版本,通过以下SQL查询可以指定的版本:
SELECT EDITION_NAME FROM ALL_EDITIONS;
那么如何在连接数据库的时候指定版本呢,可以通过在service中指定,Oracle推荐使用 srvctl
add
service
或者srvctl
modify
service
命令,通过-t
选项指定服务的默认初始会话版本。
如果连接时没有指定版本,则会使用数据库默认版本作为初始会话版本。
修改会话版本
使用 ALTER
SESSION
SET
EDITION
语句修改当前会话版本。
查看当前版本和会话版本
查看当前版本:
SELECT SYS_CONTEXT('USERENV', 'CURRENT_EDITION_NAME') FROM DUAL;
查看会话版本:
SELECT SYS_CONTEXT('USERENV', 'SESSION_EDITION_NAME') FROM DUAL;
退役版本
通过收回edition的use权限实现。
删除版本
系统默认的edition不能删除。
必须没有人使用此edition时才可删除。
或者其没有子edition,或者其子edition中没有editioned对象时才可删除。
Editioning view
由于表是不能被版本化的,那么如果要更改表的结构,如增加字段,这时就需要使用版本视图来向用户提供不同版本下的表结构。
Crossedition Triggers
如果发布版本时还涉及到数据的变化,那么就需要使用跨版本触发器。跨版本触发器分为:
- 正向跨版本触发器:将父版本表字段的数据变化同步到子版本相关字段中,在父版本触发
- 反向跨版本触发器:将子版本表字段的数据变化同步到父版本相关字段中,在子版本触发
实战
使用EBR来进行在线程序更新,具体是将HR用户下的EMPLOYEES表 PHONE_NUMBER 字段拆分为 COUNTRY_CODE和PHONE_NUMBER_WITHIN_COUNTRY两个字段 ,这里涉及到表结构和数据的变化,需要用到Editioning view和Crossedition Triggers。
准备工作
- 安装数据库
- 下载和解压 ebr.zip
配置环境
使用SYS用户连接到数据库:
SQL> conn / as sysdba
Connected.
使用HR用户连接到数据库,默认使用的是父版本ORA$BASE:
SQL> conn hr/hr
Connected.
SQL> show edition
EDITION
------------------------------
ORA$BASE
EBR准备
在SYS用户下为HR用户启用版本:
SQL> ALTER USER hr ENABLE EDITIONS;
User altered.
在HR用户下重命名需要修改的表:
SQL> ALTER TABLE employees RENAME TO employees_;
Table altered.
在HR用户下为重命名的表创建版本视图,视图的名字为表之前的名字:
SQL> CREATE EDITIONING VIEW employees AS
2 SELECT
3 employee_id, first_name, last_name, email, PHONE_NUMBER, hire_date, job_id, salary, commission_pct, manager_id, department_id
4 FROM employees_;
View created.
创建子版本
在SYS用户下基于当前默认版本Ora$Base创建新的版本post_upgrade:
SQL> CREATE EDITION post_upgrade AS CHILD OF Ora$Base;
Edition created.
使用SYS用户将版本post_upgrade的USE权限授予HR用户:
SQL> GRANT USE ON EDITION post_upgrade TO hr;
Grant succeeded.
使用子版本
在HR用户下设置当前版本为post_upgrade:
SQL> ALTER SESSION SET EDITION = post_upgrade;
Session altered.
修改表结构
在HR用户下修改employees_表结构:
SQL> ALTER TABLE employees_ ADD
2 (COUNTRY_CODE VARCHAR2(5),
3 PHONE_NUMBER_WITHIN_COUNTRY VARCHAR2(20));
Table altered.
修改版本视图
在HR用户下,在子版本post_upgrade中,修改之前在父版本Ora$Base中创建的版本视图employees,增加字段COUNTRY_CODE和PHONE_NUMBER_WITHIN_COUNTRY :
SQL> CREATE OR REPLACE EDITIONING VIEW employees AS
2 SELECT employee_id, first_name, last_name, email, phone_number, hire_date, job_id, salary, commission_pct, manager_id, department_id, phone_number_within_country, country_code
3 FROM employees_;
View created.
创建正向跨版本触发器
在HR用户下,在子版本post_upgrade中,执行脚本fwd_ce.sql,具体代码为:
-- The procedure called by empl_forward
VARIABLE Warnings VARCHAR2(4000)
begin
:Warnings := $$Plsql_Warnings;
end;
/
--------------------------------------------------------------------------------
alter session set Plsql_Warnings = ' enable:all, disable:06005, disable:06006'
/
create or replace procedure Set_Country_Code_And_Phone_No(
Phone_Number in varchar2,
Country_Code out nocopy varchar2,
Phone_Number_V2 out nocopy varchar2)
is
Char_To_Number_Error exception;
pragma Exception_Init(Char_To_Number_Error, -06502);
Bad_Phone_Number exception;
Nmbr varchar2(30) := Replace(Phone_Number, '.', '-');
function Is_US_Number(Nmbr in varchar2) return boolean is
Len number := Length(Nmbr);
Dash_Pos number := Instr(Nmbr, '-');
n pls_integer;
begin
if Len is null or Len <> 12 then
return false;
end if;
if Dash_Pos is null or Dash_Pos <> 4 then return false; end if;
begin
n := To_Number(Substr(Nmbr, 1, 3));
exception when Char_To_Number_Error then
return false;
end;
Dash_Pos := Instr(Nmbr, '-', 5);
if Dash_Pos is null or Dash_Pos <> 8 then return false; end if;
begin
n := To_Number(Substr(Nmbr, 5, 3));
exception when Char_To_Number_Error then
return false;
end;
begin
n := To_Number(Substr(Nmbr, 9));
exception when Char_To_Number_Error then
return false;
end;
return true;
end Is_US_Number;
begin
if Nmbr like '011-%' then
declare
Dash_Pos number := Instr(Nmbr, '-', 5);
begin
Country_Code := '+'||To_Number(Substr(Nmbr, 5, Dash_Pos-5));
Phone_Number_V2 := Substr(Nmbr, Dash_Pos+1);
exception when Char_To_Number_Error then
raise Bad_Phone_Number;
end;
elsif Is_US_Number(Nmbr) then
Country_Code := '+1';
Phone_Number_V2 := Nmbr;
else
raise Bad_Phone_Number;
end if;
exception when Bad_Phone_Number then
Country_Code := '+0';
Phone_Number_V2 := '000-000-0000';
end Set_Country_Code_And_Phone_No;
/
--------------------------------------------------------------------------------
declare
Stmt constant varchar2(32767) := '
alter session set Plsql_Warnings = '''||:Warnings||'''';
begin
execute immediate Stmt;
end;
/
-- The trigger empl_forward
CREATE OR REPLACE TRIGGER empl_forward
BEFORE INSERT OR UPDATE ON employees_
FOR EACH ROW
FORWARD CROSSEDITION
DISABLE
BEGIN
Set_Country_Code_And_Phone_No(
:New.Phone_Number,
:New.Country_Code,
:New.Phone_Number_Within_Country);
END;
这段代码在表employees_ 创建了一个正向跨版本触发器empl_forward,当在父版本Ora$Base上对表employees_ 进行DML操作时就会触发该触发器,将对父版本的修改传递到子版本去。
SQL> @fwd_ce.sql
PL/SQL procedure successfully completed.
Session altered.
SP2-0804: Procedure created with compilation warnings
PL/SQL procedure successfully completed.
12 /
Trigger created.
创建反向扩版本触发器
在HR用户下,在子版本post_upgrade中,执行脚本rev_ce.sql,具体代码为:
CREATE OR REPLACE TRIGGER empl_reverse
BEFORE INSERT OR UPDATE ON employees_
FOR EACH ROW
REVERSE CROSSEDITION
DISABLE
BEGIN
:NEW.phone_number :=
CASE :NEW.country_code
WHEN '+1' THEN
REPLACE(:NEW.phone_number_within_country, '-', '.')
ELSE
'011.'||LTRIM(:NEW.country_code, '+')||'.'||
REPLACE(:NEW.phone_number_within_country, '-', '.')
END;
END employees_reverse;
/
这段代码在表employees_ 创建了一个反向跨版本触发器empl_reverse,当在子版本post_upgrade上对表employees_ 进行DML操作时就会触发该触发器,将对子版本的修改传递到父版本去。
SQL> @rev_ce.sql
Trigger created.
正向操作
在HR用户下,在子版本post_upgrade中,执行脚本bulk_fwd.sql,具体代码为:
ALTER trigger empl_forward enable
/
ALTER trigger empl_reverse enable
/
DECLARE
c number := DBMS_Sql.Open_Cursor();
x number;
BEGIN
DBMS_Sql.Parse(
c => c,
Language_Flag => DBMS_Sql.Native,
Statement => 'update employees set employee_id = employee_id',
Apply_Crossedition_Trigger => 'empl_forward');
x := DBMS_Sql.Execute(c);
DBMS_Sql.Close_Cursor(c);
commit;
end;
/
这段代码先启用前面创建的两个触发器,然后执行一个update语句,并触发正向跨版本触发器empl_forward。
SQL> @bulk_fwd.sql
Trigger altered.
Trigger altered.
PL/SQL procedure successfully completed.
执行成功后,再执行脚本ver_fwd.sql查看结果,具体代码为:
--切换到父版本,执行update会触发正向跨版本触发器
ALTER SESSION SET EDITION =ORA$BASE;
SELECT phone_number FROM employees WHERE employee_id=101;
UPDATE employees SET phone_number = '515.123.4444' WHERE employee_id =101;
COMMIT;
ALTER SESSION SET EDITION = post_upgrade;
SELECT employee_id, country_code, phone_number_within_country
FROM employees WHERE employee_id =101;
执行结果如下:
SQL> @ver_fwd.sql
Session altered.
PHONE_NUMBER
--------------------
515.123.4568
1 row updated.
Commit complete.
Session altered.
EMPLOYEE_ID COUNT PHONE_NUMBER_WITHIN_
----------- ----- --------------------
101 +1 515-123-4444
在父版本插入或者更新employees_表之前,empl_forward触发器使用PHONE_NUMBER字段的新值更新字段COUNTRY_CODE和PHONE_NUMBER_WITHIN_COUNTRY。所以在子版本中,查询COUNTRY_CODE和PHONE_NUMBER_WITHIN_COUNTRY就可以看到更新的值。
反向操作
在HR用户下,在子版本post_upgrade中,执行脚本ver_rev.sql,具体代码为:
--在子版本执行update会触发反向跨版本触发器
ALTER SESSION SET EDITION =post_upgrade;
UPDATE employees SET phone_number_within_country = '515.123.4567'
WHERE employee_id =101;
SELECT employee_id, country_code, phone_number_within_country
FROM employees WHERE employee_id=101;
COMMIT;
ALTER SESSION SET EDITION = ORA$BASE;
SELECT employee_id, phone_number
FROM employees WHERE employee_id =101;
执行结果如下:
SQL> @ver_rev.sql
Session altered.
1 row updated.
EMPLOYEE_ID COUNT PHONE_NUMBER_WITHIN_
----------- ----- --------------------
101 +1 515.123.4567
Commit complete.
Session altered.
EMPLOYEE_ID PHONE_NUMBER
----------- --------------------
101 515.123.4567
当在子版本post_upgrade中向表employees_插入数据或者更新PHONE_NUMBER_WITHIN_COUNTRY字段时,就会触发empl_reverse触发器,使用PHONE_NUMBER_WITHIN_COUNTRY这个字段的新值来更新PHONE_NUMBER字段。
发布版本
通过回收HR用户对父版本的权限,来发布子版本。
--连接到HR用户,默认使用的还是父版本,查询的数据也是来自于父版本的版本视图
SQL> conn hr/hr
Connected.
SQL> show edition
EDITION
------------------------------
ORA$BASE
SQL> select * from employees where employee_id=101;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DATE JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
----------- ---------- ---------- ---------- -------------------- ----------------- ---------- ---------- -------------- ---------- -------------
101 Neena Kochhar NKOCHHAR 515.123.4567 20050921 00:00:00 AD_VP 17000 100 90
--连接到SYS用户,设置数据库的默认版本为子版本,然后退役父版本
SQL> conn / as sysdba
Connected.
SQL> ALTER DATABASE DEFAULT EDITION = post_upgrade;
Database altered.
SQL> select grantee,privilege from dba_tab_privs where table_name='ORA$BASE';
GRANTEE PRIVILEGE
------------------------------ ----------------------------------------
PUBLIC USE
SQL> REVOKE USE ON EDITION ora$base FROM PUBLIC;
Revoke succeeded.
--再次连接到HR用户,默认使用的就是子版本了,查询的数据也是来自于子版本的版本视图
SQL> conn hr/hr
Connected.
SQL> show edition
EDITION
------------------------------
POST_UPGRADE
SQL> select * from employees where employee_id=101;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DATE JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID PHONE_NUMBER_WITHIN_ COUNT
----------- ---------- ---------- ---------- -------------------- ----------------- ---------- ---------- -------------- ---------- ------------- -------------------- -----
101 Neena Kochhar NKOCHHAR 515.123.4567 20050921 00:00:00 AD_VP 17000 100 90 515.123.4567 +1
参考:
欢迎关注我的公众号,好好学习,天天向上。
Edition-Based Redefinition的更多相关文章
- Oracle PL/SQL Articles
我是搬运工....http://www.oracle-base.com/articles/plsql/articles-plsql.php Oracle 8i Oracle 9i Oracle 10g ...
- Oracle 11g Articles
发现一个比较有意思的网站,http://www.oracle-base.com/articles/11g/articles-11g.php Oracle 11g Articles Oracle Dat ...
- Oracle11g版本中未归档隐藏参数
In this post, I will give a list of all undocumented parameters in Oracle 11g. Here is a query to se ...
- Oracle Dynamic Performance Views Version 12.2.0.1
Oracle Dynamic Performance ViewsVersion 12.2.0.1 https://www.morganslibrary.org/reference/dyn_perf_v ...
- 在一个RAC集群中最多支持多少节点
How many nodes can one have in an HP-UX/Solaris/AIX/Windows/Linux cluster? Technically and since Ora ...
- Database name和SID
http://docs.oracle.com/cd/B19306_01/install.102/b15667/rev_precon_db.htm#i1027493 The Oracle Databas ...
- ABP zero 3.2 发布
v3.2.0 (2017-03-07) Common Tenant based UI customizations (allow tenants to upload custom CSS and lo ...
- Spike Notes on Lock based Concurrency Concepts
Motivation 承并发编程笔记Outline,这篇文章专注于记录学习基于锁的并发概念的过程中出现的一些知识点,为并发高层抽象做必要的准备. 尽管存在Doug Lee开山之作Concurrent ...
- A JavaFX based Game Authoring System
http://www.mirkosertic.de/doku.php/javastuff/javafxgameauthoring ——————————————————————————————————— ...
- using 40 logical processors based on SQL Server licensing SqlServer CPU核心数限制问题
公司服务器是120核心cpu,但是实际应用中只有40核,原因是业务部门发现服务器cpu承载30%的时候sql 就会卡死: 然后从sqlserver 去查询,cpu核心数: SELECT COUNT(1 ...
随机推荐
- exp(cos(t)) - 2*cos(4.*t) + (sin(t./12)).^5;图形
clc; clear all; close all; t = linspace(0,24*pi,1000); r = exp(cos(t)) - 2*cos(4.*t) + (sin(t./12)). ...
- 4.自定义view-进度条控件
1.效果 2.实现原理 画圆,画圆弧,画文字 外部控制进度,通过invalidate()方法更新 核心代码: @Override protected void onDraw(Canvas canvas ...
- 在.NET Core 中收集数据的几种方式
APM是一种应用性能监控工具,可以帮助理解系统行为, 用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题, 通过汇聚业务系统各处理环节的实时数据,分析业务系统各事务处理的交易路径和处理 ...
- FaaS,未来的后端服务开发之道
说 FaaS 先要说说 PaaS 平台即服务(Platform as a Service)是一种云计算服务,提供运算平台与解决方案堆栈即服务.在云计算的典型层级中,平台即服务层介于软件即服务与基础设施 ...
- GraduateDesign-初试APP编写(去除虚拟按键和禁止状态栏下拉)
为了毕设的要求,需要在Android系统上运行一个app来控制硬件,今天开始这个app的编写. 首先,我们的系统将只运行这个app,也就是我们不需要状态栏,虚拟按键等. 故这里将app设置为全屏模式. ...
- 循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理
在很多列表展示数据的场合中,大多数都会需要一个排序的处理,以方便快速查找排序所需的数据,本篇随笔介绍如何结合ABP后端和Vue+Element前端结合的分页排序处理过程. 1.Vue+Element前 ...
- Logstash学习之路(一)Logstash的安装
一.Logstash简介 Logstash 是一个实时数据收集引擎,可收集各类型数据并对其进行分析,过滤和归纳.按照自己条件分析过滤出符合数据导入到可视化界面.它可以实现多样化的数据源数据全量或增量传 ...
- Apache本机不同端口多站点配置:httpd-vhosts.conf(转载)
环境:Apache2.2.9,Resin-3.1.6,Win Server 2003 1.解压Resin至任意目录,我的是D:; 2. 安装Apache,具体操作下一步.下一步即可,其中要配置的地方是 ...
- go语言中运算符
Go语言学习笔记(运算符)-day01 go语言中与其他语言一样,存在多种运算符,下表列出了go语言中的运算符类型 算数运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 算数运算符 运算符 描述 ...
- PHP 爬取图片 保存本地
public function getImage($url,$filename='') { if($url == ''){ return false; } if($filename == ''){ $ ...