2011年4月20日星期三

CentOS 5.5 快速配置VNC Server

一、安装VNC Server
  yum install vnc-server

二、启动VNC Server服务:使用vncserver命令
  vncserver :n (n为桌面号)

三、配置VNC Server启动文件
  首次创建 ~HOME/.vnc/xstartup时,指定的窗口管理器是twm,它是一个极小的窗口管理器,几乎每台 X Window 系统机器上都有twm。把twm &注释掉,加上gnome-session &

四、关闭VNC Server服务
  vncserver -kill :桌面号
  例如:关闭上面的vnc连接
  vncserver -kill :1

五、VNC Server 高级设置
  1、设置vncserver启动脚本(/etc/init.d/vncserver)实现系统自启动时启动vncserver。在/etc/rc.d/rc.local文件中加入下面行。 
     /etc/init.d/vncserver start

  2、编辑/etc/sysconfig/vncservers
     VNCSERVERS="1:root"
     VNCSERVERARGS[1]="-geometry 1024x768"

  在ARGS 中修改"1024x768"来适应自己的X桌面实际参数配置。可以在这里添加任何其他VNC服务器参数配置。在VNCSERVERS中修改 root 为你希望运行VNC桌面的用户。VNCSERVERS中的1表示VNC以桌面1运行,如果希望添加其他的桌面,可以修改配置如下:
    VNCSERVERS="1:user1 2:user2 3:user3"

  3、设置vnc server的访问密码
     使用vncpasswd命令

  4、使用以下命令启动VNC:
     /etc/init.d/vncserver start

  5、查看VNC Server启动情况
     [root@CPAYNET005 ~]# netstat -tulnp
     Active Internet connections (only servers)
     Proto Recv-Q Send-Q Local Address     Foreign Address      State       PID/Program name
     tcp        0      0 0.0.0.0:5801                0.0.0.0:*             LISTEN      5248/Xvnc
     tcp        0      0 0.0.0.0:5901                0.0.0.0:*             LISTEN      5248/Xvnc
     tcp        0      0 0.0.0.0:6001                0.0.0.0:*             LISTEN      5248/Xvnc
     tcp        0      0 :::6001                     :::*                        LISTEN      5248/Xvnc
     注:如果在浏览器中通过web方式访问VNC则 端口为:5801,如果通过VNC客户端(比如VNC Viewer)来访问VNC则端口为:5901

2011年4月16日星期六

Java Concurrency In Practice读书笔记之Introduction

Benefits of Threads
1.Exploiting Multiple Processors
2.Simplicity of Modeling
  A complicated, asynchronous workflow can be decomposed into a number of simpler, synchronous workflows each running in a separate thread, interacting only with each other at specific synchronization points.
3.Simplified Handling of Asynchronous Events
  If an application goes to read from a socket when no data is available, read blocks until some data is available.If each request has its own thread, then blocking does not affect the processing of other requests.
4.More Responsive User Interfaces

Risks of Threads
1.Safety Hazards
@NotThreadSafe
public class UnsafeSequence {
    private int value;

    /** Returns a unique value. */
    public int getNext() {
        return value++;
    }
}

2.Liveness Hazards
  A liveness failure occurs when an activity gets into a state such that it is permanently unable to make forward progress. One form of liveness failure that canoccur in sequential programs is an inadvertent infinite loop, where the code that follows the loop never gets executed.Including deadlock, starvation, and livelock.

3.Performance Hazards
  Performance issues subsume a broad range of problems, including poor service time, responsiveness, throughput, resource consumption, or scalability.Context switches are more frequent in applications with many threads, and have significant costs: saving and restoring execution context, loss of locality, and CPU time spent scheduling threads instead of running them. When threads share data, they must use synchronization mechanisms that can inhibit compiler optimizations, flush or invalidate memory caches, and create synchronization traffic on the shared memory bus. All these factors introduce additional performance costs.


2011年4月15日星期五

多表连接的三种方式详解(转)

    多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join. 下面来介绍三种不同连接的不同:

一. NESTED LOOP:
    对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择。在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不能太大(大于1 万不适合),要把返回子集较小表的作为外表(CBO 默认外表是驱动表),而且在内表的连接字段上一定要有索引。当然也可以用ORDERED 提示来改变CBO默认的驱动表,使用USE_NL(table_name1 table_name2)可是强制CBO 执行嵌套循环连接。
       
    Nested loop一般用在连接的表中有索引,并且索引选择性较好的时候.

    步骤:确定一个驱动表(outer table),另一个表为inner table,驱动表中的每一行与inner表中的相应记录JOIN。类似一个嵌套的循环。适用于驱动表的记录集比较小(<10000)而且inner表需要有有效的访问方法(Index)。需要注意的是:JOIN的顺序很重要,驱动表的记录集一定要小,返回结果集的响应时间是最快的。

    cost = outer access cost + (inner access cost * outer cardinality)

 二. HASH JOIN :
    散列连接是CBO 做大数据集连接时的常用方式,优化器使用两个表中较小的表(或数据源)利用连接键在内存中建立散列表,然后扫描较大的表并探测散列表,找出与散列表匹配的行。
    这种方式适用于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。但是在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要有较大的临时段从而尽量提高I/O 的性能。
    也可以用USE_HASH(table_name1 table_name2)提示来强制使用散列连接。如果使用散列连接HASH_AREA_SIZE 初始化参数必须足够的大,如果是9i,Oracle建议使用SQL工作区自动管理,设置WORKAREA_SIZE_POLICY 为AUTO,然后调整PGA_AGGREGATE_TARGET 即可。
       
     Hash join在两个表的数据量差别很大的时候.

     步骤:将两个表中较小的一个在内存中构造一个HASH表(对JOIN KEY),扫描另一个表,同样对JOIN KEY进行HASH后探测是否可以JOIN。适用于记录集比较大的情况。需要注意的是:如果HASH表太大,无法一次构造在内存中,则分成若干个partition,写入磁盘的temporary segment,则会多一个写的代价,会降低效率。

    cost = (outer access cost * # of hash partitions) + inner access cost

三.SORT MERGE JOIN
    通常情况下散列连接的效果都比排序合并连接要好,然而如果行源已经被排过序,在执行排序合并连接时不需要再排序了,这时排序合并连接的性能会优于散列连接。可以使用USE_MERGE(table_name1 table_name2)来强制使用排序合并连接.
       
    Sort Merge join 用在没有索引,并且数据已经排序的情况.

    cost = (outer access cost * # of hash partitions) + inner access cost

    步骤:将两个表排序,然后将两个表合并。通常情况下,只有在以下情况发生时,才会使用此种JOIN方式:
    1.RBO模式
    2.不等价关联(>,<,>=,<=,<>)
    3.HASH_JOIN_ENABLED=false
    4.数据源已排序

四.  三种连接工作方式比较:
    Hash join的工作方式是将一个表(通常是小一点的那个表)做hash运算,将列数据存储到hash列表中,从另一个表中抽取记录,做hash运算,到hash 列表中找到相应的值,做匹配。
       
    Nested loops 工作方式是从一张表中读取数据,访问另一张表(通常是索引)来做匹配,nested loops适用的场合是当一个关联表比较小的时候,效率会更高。

    Merge Join 是先将关联表的关联列各自做排序,然后从各自的排序表中抽取数据,到另一个排序表中做匹配,因为merge join需要做更多的排序,所以消耗的资源更多。 通常来讲,能够使用merge join的地方,hash join都可以发挥更好的性能。

2011年4月9日星期六

Expert Oracle Database Architecture读书笔记之Transactions and Constraints

•  Atomicity: Either all of a transaction happens or none of it happens.
•  Consistency: A transaction takes the database from one consistent state to the next.
•  Isolation: The effects of a transaction may not be visible to other transactions until the transaction has committed.
•  Durability: Once the transaction is committed, it is permanent.

Transaction Control Statements 
  You should always explicitly terminate your transactions with a COMMIT or ROLLBACK; otherwise, the tool or environment you’re using will pick one or the other for you. If you exit your SQL*Plus session normally, without committing or rolling back, SQL*Plus assumes you wish to commit your work and it does so. If you just exit from a Pro*C program, on the other hand, an implicit rollback takes place.  Never rely on implicit behavior, as it could change in the future. Always explicitly COMMIT or ROLLBACK your transactions.
 Transaction control statements available to us:
•  COMMIT:
•  ROLLBACK:
•  SAVEPOINT: A SAVEPOINT allows you to create a marked point within a transaction. You may have multiple SAVEPOINTs within a single transaction.
•  ROLLBACK TO <SAVEPOINT>: This statement is used with the SAVEPOINT command. You can roll back your transaction to that marked point without rolling back any of the work that preceded it. So, you could issue two UPDATE statements, followed by a SAVEPOINT and then two DELETE statements. If an error or some sort of exceptional condition occurs during execution of the DELETE statements, and you catch that exception and issue the ROLLBACK TO SAVEPOINT command, the transaction will roll back to the named SAVEPOINT, undoing any work performed by the DELETEs but leaving the work performed by the UPDATE statements intact.
•  SET TRANSACTION: This statement allows you to set various transaction attributes, such as the transaction’s isolation level and whether it is read-only or read-write.

Atomicity 
Statement-Level Atomicity
 Oracle achieves this statement-level atomicity by silently wrapping a SAVEPOINT around each of our calls to the database. The preceding two INSERTs were really treated like this:

Savepoint statement1; 
   Insert into t values ( 1 ); 
If error then rollback to statement1; 
Savepoint statement2; 
   Insert into t values ( -1 ); 
If error then rollback to statement2; 

 In Oracle, this statement-level atomicity extends as deep as it needs to.If the INSERT INTO T fires a trigger that updates another table, and that table has a trigger that deletes from another table (and so on, and so on), either all of the work succeeds or none of it does. You don’t need to code anything special to ensure this; it’s just the way it works.

Procedure-Level Atomicity 
  Oracle treated the stored procedure call as an atomic statement. The client submitted a block of code—BEGIN P; END;—and Oracle wrapped a SAVEPOINT around it. Since P failed, Oracle restored the database back to the point right before it was called.

Transaction-Level Atomicity 


DDL and Atomicity


Durability
  Normally, when a transaction is committed, its changes are permanent—you can rely on those changes being in the database even if the database crashed the instant after the commit completed. This is not true, however, in two specific cases:
•  You use the new (as of Oracle 10g Release 2 and above) WRITE extensions available in the COMMIT statement.
•  You issue COMMITs in a non-distributed (accesses only a single database, no database links) PL/SQL block of code.

WRITE Extensions to COMMIT 
  Starting with Oracle Database 10g Release 2 and above, you may add a WRITE clause to your COMMIT
statements. The WRITE clause allows the commit to either WAIT for the redo you generated to be written to
disk (the default) or NOWAIT—to not wait—for the redo to be written. The NOWAIT option is the new capability—a capability that must be used carefully, with forethought, and with understanding of exactly what it means.
  Normally, a COMMIT is a synchronous process. Your application invokes COMMIT and then your application waits for the entire COMMIT processing to be complete

  When would you want to use this new capability to commit without waiting then? Three scenarios
come to mind:
•  A custom data load program. It must be custom, since it will have additional logic to deal with the fact that a commit might not persist a system failure.
•  An application that processes a live data feed of some sort, say a stock quote feed from the stock markets that inserts massive amounts of time-sensitive information into the database. If the database goes offline, the data stream keeps on going and the data generated during the system failure will never be processed (Nasdaq does not shut down because your database crashed, after all!). That this data is not processed is OK, because the stock data is so time-sensitive, after a few seconds it would be overwritten by new data anyway.
•  An application that implements its own “queuing” mechanism, for example one that has data in a table with a PROCESSED_FLAG column. As new data arrives, it is inserted with a value of ROCESSED_FLAG='N' (unprocessed). Another routine is tasked with reading the PROCESSED_FLAG='N' records, performing some small, fast transaction and updating the PROCESSED_FLAG='N' to 'Y'. If it commits but that commit is later undone (by a system failure), it is OK because the application that processes these records will just process the record again—it is “restartable.”

COMMITS in a Non-Distributed PL/SQL Block 
  Since PL/SQL was first introduced in version 6 of Oracle, it has been transparently using an asynchronous commit. That approach has worked because all PL/SQL is like a batch program in a way—the end user does not know the outcome of the procedure until it is completely finished. That’s also why this asynchronous commit is used only in non-distributed PL/SQL blocks of code; if we involve more than one database, then there are two things—two databases—relying on the commit being durable. When two databases are relying on the commit being durable, we have to utilize synchronous protocols or a change might be committed in one database but not the other.

ops$tkyte%ORA11GR2> create table t
  2  as
  3  select *
  4    from all_objects
  5   where 1=0
  6  /
Table created.

ops$tkyte%ORA11GR2> create or replace procedure p
  2  as
  3  begin
  4      for x in ( select * from all_objects )
  5      loop
  6          insert into t values X;
  7          commit;
  8      end loop;
  9  end;
 10  /

Logically, that code is the same as:

ops$tkyte%ORA11GR2> create or replace procedure p
  2  as
  3  begin
  4      for x in ( select * from all_objects )
  5      loop
  6          insert into t values X;
  7          commit write NOWAIT;
  8      end loop;
  9
 10      -- make internal call here to ensure
 11      -- redo was written by LGWR
 12  end;
 13  /

Distributed Transactions
  One of the really nice features of Oracle is its ability to transparently handle distributed transactions. I can update data in many different databases in the scope of a single transaction. When I commit, either I commit the updates in all of the instances or I commit none of them (they will all be rolled back). I need no extra code to achieve this; I simply “commit.” A key to distributed transactions in Oracle is the database link.
  select * from T@another_database;

  There are some, but not many, limitations to what you can do in a distributed transaction, and they are reasonable (to me, anyway, they seem reasonable). The big ones are as follows:
  •  You can’t issue a COMMIT over a database link. That is, you can’t issue a COMMIT@remote_site. You may commit only from the site that initiated the transaction.
  •  You can’t do DDL over a database link.
  •  You can’t issue a SAVEPOINT over a database link.

Autonomous Transactions 
  Autonomous transactions allow you to create a “transaction within a transaction” that will commit or roll back changes independently of its parent transaction. They allow you to suspend the currently executing transaction, start a new one, do some work, and commit or roll back—all without affecting the currently executing transaction state. Autonomous transactions provide a new method of controlling transactions in PL/SQL and may be used in
  •  Top-level anonymous blocks
  •  Local (a procedure in a procedure), stand-alone, or packaged functions and procedures
  •  Methods of object types
  •  Database triggers

How Autonomous Transactions Work
ops$tkyte%ORA11GR2> create or replace procedure Autonomous_Insert
  2  as
  3          pragma autonomous_transaction;
  4  begin
  5          insert into t values ( 'Autonomous Insert' );
  6          commit;
  7  end;
  8  /

  Note the use of the pragma AUTONOMOUS_TRANSACTION. This directive tells the database that this
procedure, when executed, is to be executed as a new autonomous transaction, independent from its parent transaction.

And here’s the “normal” NONAUTONOMOUS_INSERT procedure:
ops$tkyte%ORA11GR2> create or replace procedure NonAutonomous_Insert
  2  as
  3  begin
  4          insert into t values ( 'NonAutonomous Insert' );
  5          commit;
  6  end;
  7  /

Now let’s observe the behavior of the nonautonomous transaction in an anonymous block of
PL/SQL code:

ops$tkyte%ORA11GR2> begin
  2          insert into t values ( 'Anonymous Block' );
  3          NonAutonomous_Insert;
  4          rollback;
  5  end;
  6  /
PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select * from t;
MSG
-------------------------
Anonymous Block
NonAutonomous Insert

As you can see, the work performed by the anonymous block, its INSERT, was committed by the NONAUTONOMOUS_INSERT procedure. Both rows of data were committed, so the ROLLBACK command had nothing to roll back.

ops$tkyte%ORA11GR2> begin
  2          insert into t values ( 'Anonymous Block' );
  3          Autonomous_Insert;
  4          rollback;
  5  end;
  6  /

PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2> select * from t;
MSG
-------------------------
Autonomous Insert

  Here, only the work done by and committed in the autonomous transaction persists. The INSERT done in the anonymous block was rolled back by the ROLLBACK statement on line 4. The autonomous transaction procedure’s COMMIT has no effect on the parent transaction started in the anonymous block.

Data Integrity
Techniques for Guaranteeing Data Integrity
  When designing a database application, developers have various options for guaranteeing the integrity of data stored in the database. These options include:
・Enforcing business rules with triggered stored database procedures
・Using stored procedures to completely control access to data
・Enforcing business rules in the code of a database application
・Using Oracle Database integrity constraints, which are rules defined at the column or object level that restrict values in the database

Advantages of Integrity Constraints
  The best practice is to enforce data integrity by means other than integrity constraints only when an integrity constraint cannot be used. Advantages of integrity constraints over alternatives for enforcing data integrity include:
  ・Declarative ease
    Because you define integrity constraints using SQL statements, no additional programming is required when you define or alter a table. The SQL statements are easy to write and eliminate programming errors.
  ・Centralized rules
    Integrity constraints are defined for tables and are stored in the data dictionary. Thus, data entered by all applications must adhere to the same integrity constraints. If the rules change at the table level, then applications need not change. Also, applications can use metadata in the data dictionary to immediately inform users of violations, even before the database checks the SQL statement.
  ・Flexibility when loading data
   You can disable integrity constraints temporarily to avoid performance overhead when loading large amounts of data. When the data load is complete, you can re-enable the integrity constraints.

Types of Integrity Constraints
  Oracle Database enables you to apply constraints both at the table and column level. A constraint specified as part of the definition of a column or attribute is called an inline specification. A constraint specified as part of the table definition is called an out-of-line specification.

  Table 5-1 describes the types of constraints. Each can be specified either inline or out-of-line, except for NOT NULL, which must be inline.

Constraint Type
Description
NOT NULL
Allows or disallows inserts or updates of rows containing a null in a specified column.
Unique key
Prohibits multiple rows from having the same value in the same column or combination of columns but allows some values to be null.
Primary key
Combines a NOT NULL constraint and a unique constraint. It prohibits multiple rows from having the same value in the same column or combination of columns and prohibits values from being null.
Foreign key
Designates a column as the foreign key and establishes a relationship between the foreign key and a primary or unique key, called the referenced key.
Check
Requires a database value to obey a specified condition.
REF
Dictates types of data manipulation allowed on values in a REF column and how these actions affect dependent values. In an object-relational database, a built-in data type called a REF encapsulates a reference to a row object of a specified object type. Referential integrity constraints on REF columns ensure that there is a row object for the REF.

Nulls and Foreign Keys
  The relational model permits the value of foreign keys to match either the referenced primary or unique key value, or be null. For example, a user could insert a row into hr.employees without specifying a department ID.

Parent Key Modifications and Foreign Keys
  When a parent key is modified, referential integrity constraints can specify the following actions to be performed on dependent rows in a child table:
  ・No action on deletion or update
    In the normal case, users cannot modify referenced key values if the results would violate referential integrity.
  ・Cascading deletions
    A deletion cascades (DELETE CASCADE) when rows containing referenced key values are deleted, causing all rows in child tables with dependent foreign key values to also be deleted. 
  ・Deletions that set null
    A deletion sets null (DELETE SET NULL) when rows containing referenced key values are deleted, causing all rows in child tables with dependent foreign key values to set those values to null. 

Indexes and Foreign Keys
  As a rule, foreign keys should be indexed. The only exception is when the matching unique or primary key is never updated or deleted. Indexing the foreign keys in child tables provides the following benefits:
  ・Prevents a full table lock on the child table. Instead, the database acquires a row lock on the index.
  ・Removes the need for a full table scan of the child table. As an illustration, assume that a user removes the record for for department 10 from the departments table. 

States of Integrity Constraints
Checks for Modified and Existing Data
  You can set constraints to validate (VALIDATE) or not validate (NOVALIDATE) existing data. If VALIDATE is specified, then existing data must conform to the constraint. For example, enabling a NOT NULL constraint on employees.department_id and setting it to VALIDATE checks that every existing row has a department ID. If NOVALIDATE is specified, then existing data need not conform to the constraint.

Deferrable Constraints
  Every constraint is either in a not deferrable (default) or deferrable state. This state determines when Oracle Database checks the constraint for validity.

Nondeferrable Constraints
  If a constraint is not deferrable, then Oracle Database never defers the validity check of the constraint to the end of the transaction. Instead, the database checks the constraint at the end of each statement. If the constraint is violated, then the statement rolls back.
  For example, assume that you create a nondeferrable NOT NULL constraint for the employees.last_name column. If a user attempts to insert a row with no last name, then the database immediately rolls back the statement because the NOT NULL constraint is violated. No row is inserted.

Deferrable Constraints
  A deferrable constraint permits a transaction to use the SET CONSTRAINT clause to defer checking of this constraint until a COMMIT statement is issued. If you make changes to the database that might violate the constraint, then this setting effectively lets you disable the constraint until all the changes are complete.


  You can set the default behavior for when the database checks the deferrable constraint. You can specify either of the following attributes:
  ・INITIALLY IMMEDIATE
    The database checks the constraint immediately after each statement executes. If the constraint is violated, then the database rolls back the statement.
  ・INITIALLY DEFERRED
    The database checks the constraint when a COMMIT is issued. If the constraint is violated, then the database rolls back the transaction.


2011年4月8日星期五

Expert Oracle Database Architecture读书笔记之Concurrency and Multi-versioning

Transaction Isolation Levels

  These isolation levels are defined in terms of three “phenomena” that are either permitted or not at a given isolation level:

•  Dirty read: The meaning of this term is as bad as it sounds. You are permitted to read uncommitted, or dirty, data. You would achieve this effect by just opening an OS file that someone else is writing and reading whatever data happens to be there. Data integrity is compromised, foreign keys are violated, and unique constraints are ignored.
•  Non-repeatable read: This simply means that if you read a row at time T1 and attempt to reread that row at time T2, the row may have changed, it may have disappeared, it may have been updated, and so on.
•  Phantom read: This means that if you execute a query at time T1 and re-execute it at time T2, additional rows may have been added to the database, which will affect your results. This differs from the non-repeatable read in that with a phantomread, data you already read has not been changed, but rather that more data satisfies your query criteria than before.


  The SQL isolation levels are defined based on whether or not they allow each of the preceding phenomena.

Isolation Level
Dirty Read
Nonrepeatable Read
Phantom Read
Read uncommitted
Possible
Possible
Possible
Read committed
Not possible
Possible
Possible
Repeatable read
Not possible
Not possible
Possible
Serializable
Not possible
Not possible
Not possible


Oracle Database provides the transaction isolation levels:
 -Read Committed Isolation
 -Serializable Isolation
 -Read-Only Isolation

READ UNCOMMITTED
 UPDATE statements have two components: a read component as defined by the WHERE clause and a write component as defined by the SET clause. UPDATE statements read and write to the database; all DML statements have this ability. The case of a single row INSERT using the VALUES clause is the only exception, as such statements have no read component, just the write component. 

READ COMMITTED
In the read committed isolation level, which is the default, every query executed by a transaction sees only data committed before the query—not the transaction—began.
There are no dirty reads. There may be non-repeatable reads (i.e., rereads of the same row may return a different answer in the same transaction) and phantom reads (i.e., newly inserted and committed rows become visible to a query that were not visible earlier in the transaction). READ COMMITTED is perhaps the most commonly used isolation level in database applications everywhere, and it is the default mode for Oracle databases. 
 The really bad news in the read committed is that we are may make the end user wait for the wrong answer. We still receive an answer that never existed in the committed database state at any point in time, as with the dirty read, but this time we made the user wait for the wrong answer. 


REPEATABLE READ
 The goal of REPEATABLE READ is to provide an isolation level that gives consistent, correct answers and 
prevents lost updates.
 Most databases (not Oracle) achieve repeatable reads via the use of row-level shared read locks. A shared read lock prevents other sessions from modifying data that we have read. This, of course, decreases concurrency. Oracle opted for the more concurrent, multi-versioning model to provide read-consistent answers. 
  In Oracle, using multi-versioning, we get an answer that is consistent with respect to the point in time the query began execution. 

 If we have REPEATABLE READ enabled in a database that employs shared read locks (and not multi-
versioning), lost update errors can’t happen. The reason lost updates will not happen in those databases is because the simple act of selecting the data leaves a lock on it, and once read by our transaction, that data cannot be modified by any other transaction. Now, if your application assumes that REPEATABLE READ implies “lost updates can’t happen,” you are in for a painful surprise when you move your application to a database that does not use shared read locks as an underlying concurrency control mechanism. 

SERIALIZABLE 
 In the serialization isolation level, a transaction sees only changes committed at the time the transaction—not the query—began and changes made by the transaction itself. 
 Oracle takes an optimistic approach to serialization—it gambles on the fact that the data your transaction wants to update won’t be updated by any other transaction. This is typically the way it happens, and usually the gamble pays off, especially in quick-transaction, OLTP-type systems. If no one else updates your data during your transaction, this isolation level, which will generally decrease concurrency in other systems, will provide the same degree of concurrency as it would without SERIALIZABLE transactions. The downside to this is that you may get the ORA-08177 error if the gamble doesn’t pay off. If you think about it, however, it’s worth the risk. If you’re using SERIALIZABLE transactions, you shouldn’t expect to update the same information as other transactions. If you do, you should use the SELECT ... FOR UPDATE.
  In many other implementations, you will find this  being achieved with shared read locks and their corresponding deadlocks, and blocking. In Oracle, we do not get any blocking, but we will get the ORA-08177 error if other sessions change the data we want to change as well. 

READ ONLY 
 READ ONLY transactions are very similar to SERIALIZABLE transactions, the only difference being that they do not allow modifications, so they are not susceptible to the ORA-08177 error.  READ ONLY transactions are intended to support reporting needs where the contents of the report need to be consistent with respect to a single point in time. In other systems, you would use REPEATABLE READ and suffer the associated affects of the shared read lock.
 READ ONLY transactions are not trouble-free, however. Whereas you might see an ORA-08177 error in a SERIALIZABLE transaction, you expect to see an ORA-01555 snapshot too old error with READ ONLY 
transactions. This will happen on a system where other people are actively modifying the information you are reading. The changes (undo) made to this information are recorded in the undo segments. But undo segments are used in a circular fashion in much the same manner as redo logs. The longer the report takes to run, the better the chance that some undo you need to reconstruct your data won’t be there anymore. The undo segment will have wrapped around, and the portion of it you need would  be reused by some other transaction. At this point, you will receive the ORA-01555 error and have to start over again.  
 The only solution to this sticky issue is to have undo segments that are sized correctly for your system. Time and time again, I see people trying to save a few megabytes of disk space by having the smallest possible undo segments (“Why ‘waste’ space on something I don’t really need?” is the thought). The problem is that the undo segments are a key component of the way the database works, and unless they are sized correctly, you will hit this error. 



Implications of Multi-version Read Consistency
A Common Data Warehousing Technique That Fails
A common data warehousing technique I’ve seen people employ goes like this: 
1.  They use a trigger to maintain a LAST_UPDATED column in the source table, much like the method described in the last chapter in the “Optimistic Locking” section. 
2.  To initially populate a data warehouse table, they remember what time it is right now by selecting out SYSDATE on the source system. For example, suppose it is exactly 9:00 a.m. right now. 
3.  They then pull all of the rows from the transactional system—a full SELECT * FROM TABLE—to get the data warehouse initially populated. 
4.  To refresh the data warehouse, they remember what time it is right now again. For example, suppose an hour has gone by—it is now 10:00 a.m. on the source system. They will remember that fact. They then pull all changed records since 9:00 a.m. (the moment before they started the first pull) and merge them in. 

 They believe that they now have all of the records in the data warehouse that were modified since they did the initial pull. They may actually have all of the records, but just as likely they may not. This technique does work on some other databases—ones that employ a locking system whereby reads are blocked by writes and vice versa. But in a system where you have non-blocking reads, the logic is flawed.
 To see the flaw in this example, all we need to do is assume that at 9:00 a.m. there was at least one open, uncommitted transaction. At 8:59:30 a.m., it had updated a row in the table we were to copy. At 9:00 a.m., when we started pulling the data and thus reading the data in this table, we would not see the modifications to that row; we would see the last committed version of it. If it was locked when we got to it in our query, we would read around the lock. If it was committed by the time we got to it, we would still read around it since read consistency permits us to read only data that was committed in the database when our statement began. We would not read that new version of the row during the 9:00 a.m. initial pull, nor would we read the modified row during the 10:00 a.m. refresh. The reason? The 10:00 a.m. refresh would only pull records modified since 9:00 a.m. that morning, but this record was modified at 8:59:30 a.m. We would never pull this changed record. In many other databases where reads are blocked by writes and a committed but inconsistent read is implemented, this refresh process would work perfectly. If at 9:00 a.m. when we did the initial pull of data, we hit that row and it was locked, we would have blocked and waited for it, and read the 
committed version. If it were not locked, we would just read whatever was there, committed.  So, does this mean the preceding logic just cannot be used? No, it means that we need to get the “right now” time a little differently. We need to query V$TRANSACTION and find out which is the earliest of the current time and the time recorded in START_TIME column of this view. We will need to pull all records changed since the start time of the oldest transaction (or the current SYSDATE value if there are no active transactions):  

select nvl( min(to_date(start_time,'mm/dd/rr hh24:mi:ss')),sysdate)   from v$transaction;

In this example, that would be 8:59:30 a.m. when the transaction that modified the row started. When we go to refresh the data at 10:00 a.m., we pull all of the changes that had occurred since that time; when we merge these into the data warehouse, we’ll have everything we need. 

Write Consistency 

Consistent Reads and Current Reads 
Oracle does do two types of block gets when processing a modification statement. It performs 
•  Consistent reads: When “finding” the rows to modify 
•  Current reads: When getting the block to actually update the row of interest 

现用Oracle执行update的过程来说明Write Consistency:
  1)根据条件作一致读。该一致读SCN为update statement开始的时间。
  2)一致读中找到满足条件的记录。(this row,when we started at update-statement SCN,was interested by us )
  3)然后以当前模式(current mode)读取到数据块最新的内容(row,when was interested in consistent read),然后比较一致读和当前读的数据集。
  4)如果没有使用触发器,则只比较在where中出现的列 (predicate in consistent read) ;如果包括触发器,则还需要比较trigger内引用的:old 列。因为oracle是在一致读模式得到:old值,且在当前模式:old列可能会被改变了。
  5) 如果predicate 发生变化,则表示受到其他事务影响,则mini-rollback. 否则正常更新。assuming you are using READ COMMITTED isolation. If you are using SERIALIZABLE isolation, then at this point you would receive an ORA-08177: can't serialize access for this transaction error. 

举个例子,如果执行update t set x = 5 where y = 6;
  consistent read中y=6为最后一行,则通过consistent read找到该纪录;然后以current read 读取该块;但是发现该纪录已经被其他session将"y=6" update为 "y=7"( Tx-another), 表示该session执行的update的状态不一致,导致mini-rollback.
  In READ COMMITTED mode, after the transaction rolls back your update, the database will restart the update (i.e., change the point in time at which the update is “as of”), and instead of updating the data again, it will go into SELECT FOR UPDATE mode and attempt to lock all of the rows WHERE Y=6 for your session. Once it does this, it will run the UPDATE against that locked set of data, thus ensuring this time that it can complete without restarting.  
  因此,在batch更新之前,避免&减少mini-rollback的方法就是先select for update获得锁,再更新。






2011年4月2日星期六

Expert Oracle Database Architecture读书笔记之Locking and Latching

Pessimistic Locking 

  A row lock would be placed as soon as the user indicates his intention to perform an update on a specific row that he has selected and has visible on the screen (by clicking a button on the screen, say). That row lock would persist until the application applied the users' modifications to the row in the database and committed.

Optimistic Locking

  optimistic locking, defers all locking up to the point right before the
update is performed. 


  There are many methods of implementing optimistic concurrency control. We’ve discussed one whereby the application will store all of the before images of the row in the application itself. In the following sections, we’ll explore two others, namely:
•  Using a special column that is maintained by a database trigger or application code to tell us the “version” of the record
•  Using a checksum or hash that was computed using the original data

Optimistic Locking Using a Version Column

  This is a simple implementation that involves adding a single column to each database table you wish to protect from lost updates. This column is generally either a NUMBER or DATE/TIMESTAMP column. It is typically maintained via a row trigger on the table, which is responsible for incrementing the NUMBER column or updating the DATE/TIMESTAMP column every time a row is modified.

  I would personally prefer this column be maintained by the UPDATE statement itself, not via a trigger because triggers that are not absolutely necessary (as this one is) should be avoided. For background on why I avoid triggers, refer to my “Trouble With Triggers” article from Oracle Magazine, found on the Oracle Technology Network at http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html.

Optimistic Locking Using a Checksum 

  This is very similar to the previous version column method, but it uses the base data itself to compute a “virtual” version column. I’ll quote the Oracle 11g Release 2 PL/SQL Supplied Packages Guide (before showing how to use one of the supplied packages!) to help explain the goal and concepts behind a checksum or hash function:

  A one-way hash function takes a variable-length input string, the data, and converts it to a fixed-length (generally smaller) output string called a hash value. The hash value serves as a unique identifier (like a fingerprint) of the input data. You can use the hash value to verify whether data has been changed or not.

Optimistic or Pessimistic Locking? 

  Today, however, optimistic concurrency control is what I would recommend for most
applications. Having a connection for the entire duration of a transaction is just too high a price to pay. 
Of the methods available, which do I use? I tend to use the version column approach with a 
timestamp column. It gives me the extra update information in a long-term sense. Furthermore, it’s less 
computationally expensive than a hash or checksum, and it doesn’t run into the issues potentially 
encountered with a hash or checksum when processing LONG, LONG RAW, CLOB, BLOB, and other very
large columns.

Blocked Inserts 


  There are few times when an INSERT will block. The most common scenario is when you have a table with a primary key or unique constraint placed on it and two sessions attempt to insert a row with the same value. One of the sessions will block until the other session either commits (in which case the blocked session will receive an error about a duplicate value) or rolls back (in which case the blocked session succeeds). Another case involves tables linked together via referential integrity constraints. An INSERT into a child table may become blocked if the parent row it depends on is being created or deleted.

Deadlocks

The number one cause of deadlocks in the Oracle database, in my experience, is unindexed foreign keys. (The number two cause is bitmap indexes on tables subject to concurrent updates, which we’ll cover in Chapter 11 “Indexes”). Oracle will place a full table lock on a child table after modification of the parent table in three scenarios:
•  If you update the parent table’s primary key (a very rare occurrence if you follow the rule of relational databases stating that primary keys should be immutable), the child table will be locked in the absence of an index on the foreign key.
•  If you delete a parent table row, the entire child table will be locked (in the absence of an index on the foreign key) as well.
•  If you merge into the parent table, the entire child table will be locked (in the absence of an index on the foreign key) as well. Note this is only true in Oracle 9i and 10g and is no longer true in Oracle 11g Release 1 and above.


  An unindexed foreign key can also be problematic in the following cases:
  •  When you have an ON DELETE CASCADE and have not indexed the child table. For example, EMP is child of DEPT. DELETE DEPTNO = 10 should CASCADE to EMP. If DEPTNO in EMP is not indexed, you will get a full table scan of EMP for each row deleted from the DEPT table. This full scan is probably undesirable, and if you delete many rows from the parent table, the child table will be scanned once for each parent row deleted.
  •  When you query from the parent to the child. Consider the EMP/DEPT example again. It is very common to query the EMP table in the context of a DEPTNO. If you frequently run the following query (say, to generate a report), you’ll find that not having the index in place will slow down the queries:
   select * from dept, emp where emp.deptno = dept.deptno and dept.deptno = :X;

  When do you not need to index a foreign key? The answer is, in general, when the following
conditions are met:

•  You do not delete from the parent table.
•  You do not update the parent table’s unique/primary key value (watch for unintended updates to the primary key by tools!).
•  You do not join from the parent to the child (like DEPT to EMP).

Lock Escalation 

  If you select a row from a table with the 
FOR UPDATE clause, two locks will be created. One lock is placed on the row(s) you selected (and this will 
be an exclusive lock; no one else can lock that specific row in exclusive mode). The other lock, a ROW 
SHARE TABLE lock, is placed on the table itself. This will prevent other sessions from placing an exclusive 
lock on the table and thus prevent them from altering the structure of the table.

Lock Types
The three general classes of locks in Oracle are as follows:
•  DML locks: DML stands for Data Manipulation Language. In general this means
SELECT, INSERT, UPDATE, MERGE, and DELETE statements. DML locks are the 
mechanism that allows for concurrent data modifications. DML locks will be, for 
example, locks on a specific row of data or a lock at the table level that locks every 
row in the table. 

•  DDL locks: DDL stands for Data Definition Language, (CREATE and ALTER 
statements, and so on). DDL locks protect the definition of the structure of 
objects. 

•  Internal locks and latches: Oracle uses these locks to protect its internal data 
structures. For example, when Oracle parses a query and generates an optimized 
query plan, it will latch the library cache to put that plan in there for other sessions 
to use. A latch is a lightweight, low-level serialization device employed by Oracle, 
similar in function to a lock. Do not confuse or be misled by the term lightweight; 
latches are a common cause of contention in the database, as you will see. They 
are lightweight in their implementation, but not their effect.




DML Locks 


  DML locks are used to ensure that only one person at a time modifies a row and that no one can drop a
table upon which you are working. Oracle will place these locks for you, more or less transparently, as 
you do work. 





TX (Transaction) Locks 


In a database with a traditional memory-based lock manager, the process of locking a row would
resemble the following:
1.  Find the address of the row you want to lock.
2.  Get in line at the lock manager (which must be serialized, as it is a common in-
memory structure). 

3.  Lock the list.

4.  Search through the list to see if anyone else has locked this row.
5.  Create a new entry in the list to establish the fact that you have locked the row.
6.  Unlock the list.
Now that you have the row locked, you can modify it. Later, as you commit your changes, you must continue the procedure as follows:
1.  Get in line again.
2.  Lock the list of locks.
3.  Search through the list and release all of your locks.
4.  Unlock the list


  As you can see, the more locks acquired, the more time spent on this operation, both before and after modifying the data. Oracle does not do it that way. Oracle’s process looks like this:
1.  Find the address of the row you want to lock.
2.  Go to the row.
3.  Lock the row right there, right then—at the location of the row, not in a big list somewhere (waiting for the transaction that has it locked to end if it is already locked, unless you are using the NOWAIT option).


In Chapter 10 “Database Tables”, we’ll get into the details of the block format, but suffice it to say that at the top of a database block is some leading overhead space in which to store a transaction table for that block. This transaction table contains an entry for each real transaction that has locked some data in that block. The size of this structure is controlled by two physical attribute parameters on the CREATE statement for an object:
•  INITRANS: The initial, preallocated size of this structure. This defaults to 2 for indexes and tables.
•  MAXTRANS: The maximum size to which this structure may grow. It defaults to  255 and has a minimum of 2 practically. In Oracle 10g and above, this setting has been deprecated, so it no longer applies. MAXTRANS is 255 regardless in that release and later.


Each block starts life with, by default, two transaction slots. The number of simultaneous active transactions that a block can ever have is constrained by the value of MAXTRANS and by the availability of space on the block. You may not be able to achieve 255 concurrent transactions on the block if there is
not sufficient space to grow this structure.

TM (DML Enqueue) Locks 

TM locks are used to ensure that the structure of a table is not altered while you are modifying its
contents. For example, if you have updated a table, you will acquire a TM lock on that table. This will
prevent another user from executing DROP or ALTER commands on that table. If another user attempts 
to perform DDL on the table while you have a TM lock on it, he’ll receive the following error message: 


drop table dept
           *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

DDL Locks 

  DDL locks are automatically placed against objects during a DDL operation to protect them from changes by other sessions. For example, if I perform the DDL operation ALTER TABLE T, the table T will in
general have an exclusive DDL lock placed against it, preventing other sessions from getting DDL locks 
and TM locks on this table.


There are three types of DDL locks:
•  Exclusive DDL locks: These prevent other sessions from gaining a DDL lock or TM (DML) lock themselves. This means that you may query a table during a DDL operation, but you may not modify it in any way.
•  Share DDL locks: These protect the structure of the referenced object against modification by other sessions, but allow modifications to the data.
•  Breakable parse locks: These allow an object, such as a query plan cached in the shared pool, to register its reliance on some other object. If you perform DDL against that object, Oracle will review the list of objects that have registered their dependence and invalidate them. Hence, these locks are breakable—they do not prevent the DDL from occurring.

Latches

  Latches are lightweight serialization devices used to coordinate multiuser access to shared data structures, objects, and files.