If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import javax.swing.Timer;
public class Tetris extends JFrame {
public Tetris() {
Tetrisblok a = new Tetrisblok();
addKeyListener(a);
add(a);
}
public static void main(String[] args) {
Tetris frame = new Tetris();
JMenuBar menu = new JMenuBar();
frame.setJMenuBar(menu);
JMenu game = new JMenu("游戏");
JMenuItem newgame = game.add("新游戏");
JMenuItem pause = game.add("暂停");
JMenuItem goon = game.add("继续");
JMenuItem exit = game.add("退出");
JMenu help = new JMenu("帮助");
JMenuItem about = help.add("关于");
menu.add(game);
menu.add(help);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(220, 275);
frame.setTitle("Tetris内测版");
// frame.setUndecorated(true);
frame.setVisible(true);
frame.setResizable(false);
}
}
// 创建一个俄罗斯方块类
class Tetrisblok extends JPanel implements KeyListener {
// blockType 代表方块类型
// turnState代表方块状态
private int blockType;
private int score = 0;
private int turnState;
private int x;
private int y;
private int i = 0;
int j = 0;
int flag = 0;
// 定义已经放下的方块x=0-11,y=0-21;
int[][] map = new int[13][23];
// 方块的形状 第一组代表方块类型有S、Z、L、J、I、O、T 7种 第二组 代表旋转几次 第三四组为 方块矩阵
private final int shapes[][][] = new int[][][] {
// i
{ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },
// s
{ { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } },
// z
{ { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
// j
{ { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// o
{ { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// l
{ { 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// t
{ { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } } };
// 生成新方块的方法
public void newblock() {
blockType = (int) (Math.random() * 1000) % 7;
turnState = (int) (Math.random() * 1000) % 4;
x = 4;
y = 0;
if (gameover(x, y) == 1) {
newmap();
drawwall();
score = 0;
JOptionPane.showMessageDialog(null, "GAME OVER");
}
}
// 画围墙
public void drawwall() {
for (i = 0; i < 12; i++) {
map[i][21] = 2;
}
for (j = 0; j < 22; j++) {
map[11][j] = 2;
map[0][j] = 2;
}
}
// 初始化地图
public void newmap() {
for (i = 0; i < 12; i++) {
for (j = 0; j < 22; j++) {
map[i][j] = 0;
}
}
}
// 初始化构造方法
Tetrisblok() {
newblock();
newmap();
drawwall();
Timer timer = new Timer(1000, new TimerListener());
timer.start();
}
// 旋转的方法
public void turn() {
int tempturnState = turnState;
turnState = (turnState + 1) % 4;
if (blow(x, y, blockType, turnState) == 1) {
}
if (blow(x, y, blockType, turnState) == 0) {
turnState = tempturnState;
}
repaint();
}
// 左移的方法
public void left() {
if (blow(x - 1, y, blockType, turnState) == 1) {
x = x - 1;
}
;
repaint();
}
// 右移的方法
public void right() {
if (blow(x + 1, y, blockType, turnState) == 1) {
x = x + 1;
}
;
repaint();
}
// 下落的方法
public void down() {
if (blow(x, y + 1, blockType, turnState) == 1) {
y = y + 1;
delline();
}
;
if (blow(x, y + 1, blockType, turnState) == 0) {
add(x, y, blockType, turnState);
newblock();
delline();
}
;
repaint();
}
// 是否合法的方法
public int blow(int x, int y, int blockType, int turnState) {
for (int a = 0; a < 4; a++) {
for (int b = 0; b < 4; b++) {
if (((shapes[blockType][turnState][a * 4 + b] == 1) && (map[x
+ b + 1][y + a] == 1))
|| ((shapes[blockType][turnState][a * 4 + b] == 1) && (map[x
+ b + 1][y + a] == 2))) {
return 0;
}
}
}
return 1;
}
// 消行的方法
public void delline() {
int c = 0;
for (int b = 0; b < 22; b++) {
for (int a = 0; a < 12; a++) {
if (map[a][b] == 1) {
c = c + 1;
if (c == 10) {
score += 10;
for (int d = b; d > 0; d--) {
for (int e = 0; e < 11; e++) {
map[e][d] = map[e][d - 1];
}
}
}
}
}
c = 0;
}
}
// 判断你挂的方法
public int gameover(int x, int y) {
if (blow(x, y, blockType, turnState) == 0) {
return 1;
}
return 0;
}
// 把当前添加map
public void add(int x, int y, int blockType, int turnState) {
int j = 0;
for (int a = 0; a < 4; a++) {
for (int b = 0; b < 4; b++) {
if (map[x + b + 1][y + a] == 0) {
map[x + b + 1][y + a] = shapes[blockType][turnState][j];
}
;
j++;
}
}
}
// 画方块的的方法
public void paintComponent(Graphics g) {
super.paintComponent(g);
// 画当前方块
for (j = 0; j < 16; j++) {
if (shapes[blockType][turnState][j] == 1) {
g.fillRect((j % 4 + x + 1) * 10, (j / 4 + y) * 10, 10, 10);
}
}
// 画已经固定的方块
for (j = 0; j < 22; j++) {
for (i = 0; i < 12; i++) {
if (map[i][j] == 1) {
g.fillRect(i * 10, j * 10, 10, 10);
}
if (map[i][j] == 2) {
g.drawRect(i * 10, j * 10, 10, 10);
}
}
}
g.drawString("score=" + score, 125, 10);
g.drawString("抵制不良游戏,", 125, 50);
g.drawString("拒绝盗版游戏。", 125, 70);
g.drawString("注意自我保护,", 125, 90);
g.drawString("谨防受骗上当。", 125, 110);
g.drawString("适度游戏益脑,", 125, 130);
g.drawString("沉迷游戏伤身。", 125, 150);
g.drawString("合理安排时间,", 125, 170);
g.drawString("享受健康生活。", 125, 190);
}
// 键盘监听
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
down();
break;
case KeyEvent.VK_UP:
turn();
break;
case KeyEvent.VK_RIGHT:
right();
break;
case KeyEvent.VK_LEFT:
left();
break;
}
}
// 无用
public void keyReleased(KeyEvent e) {
}
// 无用
public void keyTyped(KeyEvent e) {
}
// 定时器监听
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
if (blow(x, y + 1, blockType, turnState) == 1) {
y = y + 1;
delline();
}
;
if (blow(x, y + 1, blockType, turnState) == 0) {
if (flag == 1) {
add(x, y, blockType, turnState);
delline();
newblock();
flag = 0;
}
flag = 1;
}
;
}
}
}
The goal of JavaMelody is to monitor Java or Java EE applications servers in QA and production environments. It is not a tool to simulate requests from users, it is a tool to measure and calculate statistics on real operation of an application depending on the usage of the application by users.
JavaMelody is opensource (LGPL) and production ready: in production in an application of 25 person years. JavaMelody is easy to integrate in most applications and is lightweight (no profiling and no database).
JavaMelody is mainly based on statistics of requests and on evolution charts.
It allows to improve applications in QA and production and help to:
- give facts about the average response times and number of executions
- make decisions when trends are bad, before problems become too serious
- optimize based on the more limiting response times
- find the root causes of response times
- verify the real improvement after optimizations
It includes summary charts showing the evolution over time of the following indicators:
- Number of executions, mean execution times and percentage of errors of http requests, sql requests, jsp pages or methods of business façades (if EJB3, Spring or Guice)
- Java memory
- Java CPU
- Number of user sessions
- Number of jdbc connections
These charts can be viewed on the current day, week, month, year or custom period.
JavaMelody includes statistics of predefined counters (as of today http requests, sql requests, jsp pages and methods of business façades if EJB3, Spring or Guice) with, for each counter :
- A summary indicating the overall number of executions, the average execution time, the cpu time and the percentage of errors.
- And the percentage of time spent in the requests for which the average time exceeds a configurable threshold.
- And the complete list of requests, aggregated without dynamic parameters with, for each, the number of executions, the mean execution time, the mean cpu time, the percentage of errors and an evolution chart of execution time over time.
- Furthermore, each http request indicates the size of the flow response, the mean number of sql executions and the mean sql time.
It also includes statistics on http errors, on warnings and errors in logs, on data caches if ehcache and on batch jobs if quartz.
An optional and independent collect server may be used if necessary to unload the application of storage management, and of reports generation and to centralize the data of clustered applications or of several applications.
JavaMelody users’ group is at http://groups.google.com/group/javamelody (email: javamelody@googlegroups.com).
Hudson “Monitoring” plugin with JavaMelody is available in Hudson management page and described here
http://code.google.com/p/javamelody/
我很小的时候住在外婆家,一直到4岁左右才从我外婆家搬出来,因为隔的地方不 远,基本上每个星期都会去,有时候我妈揍我我也会跑到我外婆家去,印象很深刻的是5岁那一次傍晚的时候我妈要揍我,我跑的可快了,我妈还没撒腿追的时候我 就没踪影了,一口气跑到我外婆家,我妈后来到处找我,找到后带回家又是一顿暴揍。我和我外婆家的人都很亲近,和我的舅舅们就和哥们似的。
我小的时候外婆家很穷,我很少见到我外公,天蒙蒙亮就出去,晚上很晚才回来,忙的全是地里的活,忙忙碌碌一直到生病直至去世。我的大舅身体很不好,动了手 术后背部有很大一块凸骨,个子很矮,我玩到很晚的时候突然记起来要回家就吵着我舅舅送我,我外婆就会抓把米放到我口袋,说是辟邪,在路上撒撒鬼怪就不会害 你,我外婆家到我家的路上有一个坡,现在看起来感觉很平,但那时候我舅舅骑自行车下坡的时候总把我吓个半死,吓得我死死的抱着他,我舅舅就会哈哈大笑,小 时候我觉得我的大舅就像我的父亲。我舅舅长的一点不都强悍,因为身材很矮小,所以很多方面都很吃亏,他喜欢喝酒,我16岁的时候就开始和我的舅舅们喝白 酒,无话不谈。我舅舅和他老婆总是嘻嘻哈哈的,他很疼爱他老婆,什么事都依她,他老婆也让他很疼,我表弟10多岁的时候,我舅妈就走了,一直都没回来,我 舅舅又当爹又当妈的,我表弟17岁的时候他还抱着坐膝盖上。我舅妈走后的好几年,别人给我舅舅介绍老婆,呆的最久的也就两三个月,害我白叫别人舅妈好几 次。
我舅舅是个民工,做的都是很辛苦的事情,稍微好点的区别也是晒不晒太阳的说法,有事做的时候会出去几个月不回家,而且还要手艺好的人才行,有时候我外婆生 病我舅舅他们也会赶回来,匆匆忙忙看看又上工地干活,没事做的人都想办法找事情做,能够多挣一天算一天,基本上闲不下来。我舅舅是那种典型的上有老下有小 收入不高干体力活养活的人,国家大事和他们无关,他们干的都是人民的住房大事,这代人的希望全部都寄托在孩子身上,会读书的哪怕是卖血也会送他们上学,读 书不行的就想办法让孩子学门手艺,至少有一技傍生不会饿死。
我舅舅已经四十多岁了,去年在内蒙古工地做了半年事情,他打电话和我说那里好冷,但还得上高架,因为工价要稍高。我表弟去年还在学校上学,两年的时间花了 四万多块钱,四万块钱并不是一次性拿出来,是每一天每一天干活积累一个月又寄过去,我舅舅充满了希望,虽然他和我说他没有什么希望,只是做一个父亲应该做 的事情。上一辈人成就了我们也害了我们,似乎是命中注定。
这是可以改变的事实,而那把筛子正抓在我们手里,就看你有没有勇气和智慧把一手烂牌打好。
我盼望着和我的父辈们把酒言欢,没有时间,没有拘束。
早在几个星期前,Adobe就发布了Dreamweaver CS5 HTML5 Pack的预览版下载。众所周知,HTML5在互联网领域掀起了一场大论战,并让Adobe的日子很难熬。HTML5致力于为前端开发提供全面的标记语 言。以下30多个资源可帮你开始学习HTML5。
Blowing up HTML5 video and mapping it into 3D space(将HTML5视频吹散并组成3D效果)
最近我研究了HTML 5中的Canvas 和Video 标签,并发现了一些很酷的特性。其中之一就是Canvas.drawImage() api。此为详细介绍。
Code a Backwards Compatible, One Page Portfolio with HTML5 and CSS3(用HTML5 和CSS3 打造向下兼容的网页)
HTML5更加语义化,使用HTML5 我们不必在网页上布满没有意义的div。它引入了有意义的tag,比如 navigations 和 footers 使代码更有意义也更接近自然语言。
Coding A HTML 5 Layout From Scratch(HTML 5 布局)
这篇文章将教你
- 用原有技术将元素放置在特定位置
- 最新的技术潮流
- Microformats与HTML5协同使用
- 介绍HTML5与CSS3的新特性
Coding a CSS3 and HTML5 One Page Website Template(制作CSS3和 HTML5 一页式站点模板)
这篇文章介绍了如何利用CSS3 和jQuery的新特性制作HTML5 网页模版。 HTML5 仍在完善当中,你也可以选择性的下载XHTML版。
Comprehensive video tutorial on HTML5(全面的HTML5视频指南)
这 是一个叫Brad Neuberg的工程师制作的HTML5教学视频。
Create modern Web sites using HTML5 and CSS3(用HTML5与CSS3打造时尚站点)
这篇文章介绍了许多HTML5的功能和语法及 API,还有CSS3的新的选择器,效果和特性。最 后, 还将教你如何利用这些新特性开发一个网页。当你读完这篇文章,你就能用HTML5和CSS3开发一个自己的站点啦。
Designing a blog with html5(用html5设计博客)
许多HTML5 特性要结合JavaScript API一起使用,以增加网页的互动性。但仍有一些新元素可让传统的Web1.0页面更加语义化。为了学习这些,我们来看怎样建立一个博客。
Designing for the Future with HTML5 and CSS3 : Tutorials and Best Practices(为未来设计:HTML 5 和 CSS3 指南与最佳案例)
这篇文章将介绍用 HTML5和CSS3搭建的几个最佳站点。
Design and Code a Cool iPhone App Website in HTML5(用HTML5设计和实现一个超酷 iPhone App 网站)
Have a Field Day with HTML5 Forms(建立HTML 5表格)
这篇文站将教你 如果用HTML 5 和高级CSS技术与最新的CSS3技术建立一个漂亮的表格。
How To Create A Nice Blog Design Touching The Future(不用photoshop,完成网页设计)
How to Make All Browsers Render HTML5 Mark-up Correctly – Even IE6(怎样让所有浏览器都渲染HTML5标记——即使是IE6)
这篇文章将教你如何用JavaScript和 CSS,使 HTML5页面向下兼容,即使是IE6也不例外。
How to Make an HTML5 iPhone App(制作HTML5 iPhone 应用)
这是 一篇针对iPhone的指导,但是许多技术也可用在兼容HTML5的手机浏览器上。
HTML 5 and CSS 3: The Techniques You’ll Soon Be Using(HTML 5 和CSS 3:你将用到的技术)
这篇文章使用HTML 5和CSS 3 搭建博客页面。如果你已经熟悉html 和CSS,将很容易跟上。
HTML5 for Beginners. Use it now, its easy!(HTML 5初学指南)
给 所有具有基础HTML知识的初学者的HTML 5 入门指南
HTML5 Presentation
这篇文章介绍了HTML5 的发展历史和它的基本特性
HTML5 Tutorial – Getting Started(HTML 5 入门指导)
How to Build Web Pages With HTML 5(怎样建立HTML 5网页)
Simple Website Layout Tutorial Using HTML 5 and CSS 3(HTML5和CSS3布局指南)
HTML5最令人期待的新标签包 括<header>, <footer>, <aside>, <nav>, <audio>,同时它还包括画图,线下存储数据,拖放等API。页面布局将会更易理解。这里将介绍一个最简单的HTML 5 布局页面,用CSS3 设置样式。最终结果如下
Structural Tags in HTML5(HTML 5 结构标签)
HTML5 有许多标签帮助网页结构化,这能省去以网页中许多div
HTML5 Boilerplates(HTML 5模板)
此文介绍了一些你能拿来就用的HTML5 模板文件
HTML 5 canvas – the basics(HTML 5 基础——Canvas)
对HTML 5 Canvas使用方法的全面指导
Implementing HTML5 Drag and Drop: New Premium Tutorial(HTML 5 拖放)
HTML5 的一个新特性就是拖放,不过IE早在5.5时代就支持拖放了,而HTML 5 的拖放也是基于IE的。本例将教你如果用拖放实现一个简单的购物车界面。
Preview of HTML 5
这是一篇比较老的文章,介绍了HTML5的特性和优 点。
The HTML 5 Canvas For Flash Developers : Drawing(HTML 5 Canvas 的画图功能)
The Power of HTML 5 and CSS 3
介绍了HTML 5 与CSS3能创造的各种效果。
View Source Tutorial: Sticky Notes With HTML5 and CSS3(HTML5 和CSS3 打造便利贴效果)
webOS HTML5 Database Storage Tutorial(webOS HTML5 数据存储指南)
HTML5 的本地存储功能将使数据存储十分简便。
Yes, You Can Use HTML 5 Today!
本文介绍了一些现已被支持的HTML 5 特性,对初学者十分有用。
文章来源:NTT.cc
翻译:lovelyashes
转自:http://blog.csdn.net/Vanessa219/archive/2010/06/09 /5658910.aspx#1412768
| JDBC隔离级别 | 数据库隔离级别 | 数据访问情况 |
| TRANSACTION_READ_UNCOMMITTED(未提交的读)Uncommitted Read | ur | 就是俗称“脏读”(dirty read),在没有提交数据时能够读到已经更新的数据 |
| TRANSACTION_READ_COMMITTED (游标稳定性)Cursor Stability | cs | 在一个事务中进行查询时,允许读取提交前的数据,数据提交后,当前查询就可 以读取到数据。update数据时候并不锁住表 |
| TRANSACTION_REPEATABLE_READ (读稳定性)Read Stability | rs | 在一个事务中进行查询时,不允许读取其他事务update的数据,允许读取 到其他事务提交的新增数据 |
| TRANSACTION_SERIALIZABLE (可重复的读)Repeatable Read | rr | 在一个事务中进行查询时,不允许任何对这个查询表的数据修改。 |
“可重复的读”隔离级别rr
当使用可重复的读隔离级别时,在单个事务执行期间锁定该事务引用的所有行。使用这种隔离级别时,同一事务多次发出的同一个 SELECT 语句将始终产生同一结果;丢失更新、脏读、不可重复的读、幻像都不会发生。
使用可重复的读隔离级别的事务可以多次检索同一行集,并可以对它们执行任意次操作,直到由提交或回滚操作终止事务;不允许其它事务执行插入、更新或删除操 作,因为这些操作会在隔离事务存在期间影响正在被使用的行集。为了确保在“可重复的读”隔离级别下运行的事务所访问的数据不会受其它事务的负面影响,所以 锁定了该隔离事务所引用的每个行 — 而不是仅锁定被实际检索和/或修改的那些行。因此,如果一个事务扫描了 1000 行但只检索 10 行,则所扫描的 1000 行(而不仅是被检索的 10 行)都会被锁定。
那么在现实环境中这个隔离级别是如何工作的呢?假定您拥有一家大型旅馆,并有一个网站,该网站按“先到先服务”的原则接受客户的房间预订。如果您的旅馆预 订应用程序是在“可重复的读”隔离级别下运行的,当客户检索某个日期段内的所有可用房间列表时,您将无法更改那些房间在指定日期范围内的费用,而其他客户 也将无法进行或取消将会更改该列表的预订,直到生成该列表的事务终止为止。(对于第一个客户的查询所指定范围之外的任何房间,您都可以更改房价,其他客户 也都可以进行或取消房间预订。)
“读稳定性”隔离级别rs
当使用读稳定性隔离级别时,在单个事务执行期间,会锁定该事务所检索的所有行。当使用这种隔离级别时,直到隔离事务终止之前,其它事务不能更改隔离事务读 取的所有行。此外,其它事务对其它行所作的更改,在提交之前对于运行在“读稳定性”隔离级别下的事务而言是不可见的。因此,当使用“读稳定性”隔离级别 时,在同一事务中多次发出 SELECT 语句可能会产生不同的结果。丢失更新、脏读和不可重复的读都不会发生;但是,有可能出现幻像。
使用“可重复的读”隔离级别时,隔离事务引用的每一行都被锁定;但是,在“读稳定性”隔离级别下,只锁定隔离事务实际检索和/或修改的行。因此,如果一个 事务扫描了 1000 行但只检索 10 行,则只有被检索到的 10 行(而不是所扫描的 1000 行)被锁定。
那么,这种隔离级别会如何改变旅馆预订应用程序的工作方式呢?现在,当一个客户检索某个日期段内的所有可用房间列表时,您可以更改旅馆中任何房间的房价, 而其他客户也可以取消在第一个客户的查询所指定的日期段内所保留房间的预订。因此,如果在终止提交查询的事务之前再次生成列表,则产生的新列表中有可能包 含新的房价或第一次产生列表时不可用的房间。
“游标稳定性”隔离级别cs
当使用游标稳定性隔离级别时,只要隔离事务所用的游标定位在某一行上,就会锁定该游标所引用的这一行。所获取的锁一直有效,直到游标重定位(通常通过调用 FETCH 语句)或隔离事务终止为止。因此,当使用这种隔离级别时,在同一事务中多次发出 SELECT 语句可能会产生不同的结果。丢失更新和脏读不会发生;但有可能出现不可重复的读和幻像。
当使用“游标稳定性”隔离级别的事务通过可更新游标从表中检索行时,在游标定位在该行上时,其它事务不能更新或删除该行。但是,如果被锁定的行本身不是用 索引访问的,那么其它事务可以将新的行添加到表,并对位于被锁定行前后的行进行更新和/或删除操作。此外,如果隔离事务修改了它检索到的任何行,那么在隔 离事务终止之前,即使在游标不再位于这个被修改的行,其它事务不能更新或删除该行。
其它事务在其它行上进行的更改,在提交之前对于使用“游标稳定性”隔离级别的事务是不可见的。缺省情况下,大多数事务都使用“游标稳定性”隔离级别。
这种隔离级别对旅馆预订应用程序有什么影响呢?现在,当一个客户检索某个日期段内的所有可用房间列表,然后查看关于所产生的列表上每个房间的信息时(每次 查看一个房间),您可以更改旅馆中任何房间的房价,而其他客户可以对任何日期段的任何房间进行或取消预订;唯一的例外是第一个客户当前正在查看的房间。当 第一个客户查看列表中另一个房间的信息时,对于这个新房间也是一样;您现在可以更改第一个客户刚才查看的房间的房价,其他客户也可以预订该房间,但不能对 第一个客户当前正在查看的房间进行这些操作。
“未提交的读”隔离级别ur
在使用未提交的读隔离级别的情况中,当单个事务检索行时,仅当另一个事务试图删除或更改被检索的行所在的表时,才会在单个事务期间锁定这些行。因为在使用 这种隔离级别时,行通常保持未锁定状态,所以丢失更新、脏读、不可重复的读和幻像都可能会发生。
在大多数情况下,其它事务对行所作的更改,在提交或回滚之前对于使用“未提交的读”隔离级别的事务是可见的。但是,此类事务不能看见或访问其它事务所创建 的表、视图或索引,直到那些事务被提交为止。类似地,如果其它事务删除了现有的表、视图或索引,使用“未提交的读”隔离级别的事务仅当进行删除操作的事务 终止时才能了解这一情况。这种行为有一个例外:当运行在“未提交的读”隔离级别下的事务使用可更新游标时,该事务的行为和在“游标稳定性”隔离级别下运行 一样,并应用“游标稳定性”隔离级别的约束。
“未提交的读”隔离级别通常用于那些访问只读表的事务和/或某些执行 SELECT 语句的事务,这些语句对其它事务的未提交数据没有负面效果。
那么这种隔离级别对旅馆预订应用程序有什么影响呢?现在,当一个客户检索某个日期段内的所有可用房间列表时,您可以更改旅馆中任何房间的房价,而其它客户 也可以对任何日期段内的任何房间进行或取消预订。此外,如果其它客户取消了预订,即使他们还没有终止其事务并将那些取消提交到数据库,所生成的列表就可以 包含这些取消预订的房间了。
2. 数据库之间的差异:
1).Oracle通过具有意向锁的多粒度封锁机制进行并发控制,保证数据的一致性。其DML锁 (数据锁)分为两个层次(粒度):即表级和行级。通常的DML操作在表级获得的只是意向锁(RS或RX),其真正的封锁粒度还是在行级;DB2也是通过具 有意向锁的多粒度封锁机制进行并发控制,保证数据的一致性。其DML锁(数据锁)分为两个层次(粒度):即表级和行级。通常的DML操作在表级获得的只是 意向锁(IS,SIX或IX),其真正的封锁粒度也是在行级;另外,在Oracle数据库中,单纯地读数据(SELECT)并不加锁,这些都提高了系统的 并发程度,Oracle强调的是能够”读”到数据,并且能够快速的进行数据读取。而DB2的锁强调的是”读一致性”,进行读数据(SELECT)时会根据 不同的隔离级别(RR,RS,CS)而分别加 S,IS,IS锁,只有在使用UR隔离级别时才不加锁。从而保证不同应用程序和用户读取的数据是一致的。
2). 在支持高并发度的同时,DB2和Oracle对锁的操纵机制有所不同:Oracle利用意向锁及数据行上加锁标志位等设计技巧,减小了Oracle维护行 级锁的开销,使其在数据库并发控制方面有着一定的优势。而DB2中对每个锁会在锁的内存(locklist)中申请分配一定字节的内存空间,具体是X锁 64字节内存,S锁32字节内存(注:DB2 V8之前是X锁72字节内存而S锁36字节内存)。
3). Oracle数据库中不存在锁升级,而DB2数据库中当数据库表中行级锁的使用超过locklist*maxlocks会发生锁升级。
4). 在Oracle中当一个session对表进行insert,update,delete时候,另外一个session仍然可以从Orace回滚段或者还 原表空间中读取该表的前映象(before image); 而在DB2中当一个session对表进行insert,update,delete时候,另外一个session仍然在读取该表数据时候会处于lock wait状态,除非使用UR隔离级别可以读取第一个session的未提交的值;所以Oracle同一时刻不同的session有读不一致的现象,而 DB2在同一时刻所有的session都是”读一致”的。
5). db2缺省下是使用cs级别,oracle缺省是使用ur.
for example: WITH UR
