??xml version="1.0" encoding="utf-8" standalone="yes"?>
一个事务读到另一个事务,未提交的修改,是脏读。这里所谓的修改Q除了Update操作,不要忘了,q包?br /> Insert和Delete操作?/p>
脏读的后果:如果后一个事务回滚,那么它所做的修改Q统l都会被撤销。前一个事务读到的数据Q就是垃圾数据?/p>
举个例子Q预订房间?br />
有一张Reservation表,往表中插入一条记录,来订购一个房间?/p>
事务1Q在Reservation表中插入一条记录,用于预订99h间?/p>
事务2Q查询,未预定的房间列表,因ؓ99h_已经被事?预订。所以不在列表中?/p>
事务1Q信用卡付款。由于付Ƒ֤败,D整个事务回滚?br /> 所以插入到Reservation 表中的记录ƈ不置为持久(卛_被删除Q?/p>
现在99h间则为可用?br /> 所以,事务2所用的是一个无效的戉K列表Q因?9h_已经可用。如果它是最后一个没有被预定的房_那么q将是一个严重的p?/p>
注:脏读的后果很严重?/p>
2Q不可重复读?/p>
在同一个事务中Q再ơ读取数据时【就是你的select操作】,所d的数据,和第1ơ读取的数据Q不一样了。就是不可重复读?/p>
举个例子Q?br /> 事务1Q查询有双h床房间?9h_有双人床?/p>
事务2Q将99h_Ҏ单h床房间?/p>
事务1Q再ơ执行查询,h所有双人床戉K列表Q?9h间不再列表中了。也是_
事务1Q可以看到其他事务所做的修改?/p>
在不可重复读Q里面,可以看到其他事务所做的修改Q而导?ơ的查询l果不再一样了?br />
q里的修改,是提交过的。也可以是没有提交的Q这U情况同时也是脏诅R?/p>
如果Q数据库pȝ的隔ȝ别。允许,不可重复诅R那么你启动一个事务,q做一个select查询操作?br />
查询到的数据Q就有可能,和你W?ơ,3?..nơ,查询到的数据不一栗一般情况下Q你只会做一ơ,select
查询Qƈ以这一ơ的查询数据Q作为后l计的基础。因为允许出玎ͼ不可重复诅R那么Q?br />
时候,查询到的数据Q都有可能被其他事务更新Q查询的l果是不确定的?/p>
注:如果允许Q不可重复读Q你的查询结果,是不确定的。一个不定的结果,你能容忍吗?
3Q?/p>
事务1d指定的where子句所q回的一些行。然后,事务2插入一个新行,q个新行也满事?使用的查?br />
where子句。然后事?再次使用相同的查询读取行Q但是现在它看到了事?刚插入的行。这个行被称为象,
因ؓ对事?来说Q这一行的出现是不可思议的?/p>
举个例子Q?br /> 事务1Q请求没有预定的Q双人床戉K列表?br /> 事务2Q向Reservation表中插入一个新U录Q以预订99h_q提交?br /> 事务1Q再ơ请求有双h床的未预定的戉K列表Q?9h_不再位于列表中?/p>
注:q读Q针对的是,Insert操作。如果事?Q插入的记录Q没有提交。那么同时也是脏诅R?/p>
U性表的静态单链表存储l构 :
#define MAXSIZE 100;
typedef struct{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];
分析 :
q种描述Ҏ便于在不?/span> ?/font> 指针 ?/font> cd的高U程序设计语a?/span> , 使用的链表结?/span> . 数组的零分量可看成头节点 . q种l构仍然需要预先分配一个较大的I间 . 但在插入和删除的时?/span> , 不需要移动元?/span> . 仅需要修Ҏ?/span> . 所以仍然具有链式存储结构的主要优点 .
(1) 在静态单链表?/span> , 查找W一个gؓ e 的元?/span> .
int LocateElem_L(SLinkList S, ElemType e)
{
i = S[0].cur;
while(i && S[i].data != e) i=S[i].cur;
return i;
}
分析
:
如果找不到相应的元素
,
q回gؓ
0.
(2)
一l数l?/span>
space
中的各个分量
,
链成一个备用的链表
.
space[0].cur
为头指针
.
void InitSpace(SLinkList &space){
for(i =0;i<MAXSIZE-1;++i)
space[i].cur = i+1;
space[MAXSIZE-1].cur =0;
}
(3) 如果备用I间的链表非I?/span> , 则返回分配的节点下标 ,
否则 , q回 0;
int Malloc_SL(SLinkList &space){
i=space[0].cur;
if(space[0].cur)
space[0].cur =space[i].cur;
return i;
}
(4) 下标ؓ k 的空闲节点回收到备用链表 .
void Free_SL(SLinkList &space,int k)
{
space[k].cur =space[0].cur;
space[0].cur = k;
}
(4)
计算集合q算
(A-B
)
?/span>
(B-A)
假设q端输入集合元?/span>
,
先徏立表C集?/span>
A
的静态链?/span>
S,
然后在输入集?/span>
B
的元素的同时查找
S
?/span>
,
如果存在相同的元?/span>
,
则从
S
表中删除
,
否则其插入?/span>
S
表中
.
具体代码如下
:
void difference(SLinkList &space , int &s)
{
InitSpace_SL(space);
s = Malloc_SL(space);
r=s;
scanf(m,n);
for(j=1;j<=m;++j)
{ i =Malloc_SL(space);
scanf(space[i].data);
space[r].cur =i;
r=i;
} space[r].cur=0;
for
(j=1;j<=n;++j){
scanf(b);
p=s;k=space[s].cur;
while(k!=space[r].cur && space[k].data !=b)
{ p=k;k=space[k].cur;}
if
(k==space[r].cur)
{
i = Malloc_SL(space);
space[i].data = b;
space[i].cur = space[r].cur;
space[r].cur = i;
r=i;
}
else{
space[p].cur =space[k].cur;
Free_SL(space,k);
if(r==k)
r=p;
}
}
}
铑ּ存储表示 :
typedef struct LNode{
ElemType data;
Struct LNode *next;
}LNode,*LinkList;
基本操作在链表上的实?/span> :
(1) 单链表的取元素算法(l典Q?/span>
Status GetElem_L(LinkList L, int i,ElemType &e)
{
p=L->next; j=1;
while(p && j<i)
{
p=p->next;++j;
}
if(!p || j>i) return ERROR;
e=p->data;
return OK;
}
法分析
:
基本操作?/span>
:
比较
j
?/span>
I,
q把指针后移
,
循环体执行的ơ数
,
与被查元素的位置有关
.
假设表长?/span>
n,
如果
1<=i<=n,
那么循环体中语句的执行次Cؓ
i-1.
否则ơ数?/span>
n
所以时间复杂度?/span>
O(n).
Status ListInsert_L(LinkList &L, int i,ElemType e)
{
p=L;j=0;
while(p&&j<i-1)
{ p=p->next;++j}
if(!p || j>i-1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next =s;
return OK;
}
(3)
删除元素法
Status ListDelete_L(LinkList &L, int i,ElemType &e)
{
p=L;j=0;
while(p &&j<i-1)
{p=p->next;++j}
if(!p ||j>i-1)
return ERROR;
q=p->next;
p->next =q->next;
e =q->data;
free(q);
return OK;
}
法分析
:
插入和删除算?/span>
,
都要先找到第
i-1
个节?/span>
,
所以时间复杂度?/span>
O(n);
void CreateList_L(LinkList &L,int n){
L =(LinkList)malloc(sizeof(LNode));
L->next = null;
for(i = n;i>0;--i){
p =(LinkList)malloc(sizeof(LNode));
scanf(&p->data);
p->next = L->next;
L->next =p;
}
}
法分析 :
按照逆序循环输入 n 个数据元素的?/span> , 建立新节?/span> . q插?/span> . 因此法的时间复杂度?/span> O(n).