⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 -

📁 介绍了数据库方面的基础知识
💻
📖 第 1 页 / 共 2 页
字号:
$OPEN mycurs//打开滚动游标 
for(;;) 
{$FETCH mycurs INTO $Id,$Mdeposit,$Mpayout,$Mbalance; //从游标中读取记录值 
if sqlcode=SQLNOTFOUND then exit; //如果读完,退出循环 
….//显示记录内容给用户看 
….//如果用户决定要修改记录,则继续执行 
$DECLARE mycurs_update CURSOR FOR SELECT Mdeposit,Mpayout,Mbalance 
FROM Acount WHERE Id=$Id; //定义更新游标 
$FETCH mycurs_UPDATE INTO $Mdeposit,$Mpayout,$Mbalance; //读取数值 
$UPDATE acount SET (Mdeposit,Mpayout,Mbalance)= ( $Mdeposit,$Mpayout,$Mbalance) 
WHERE CURRENT of mycurs_update; //更新数值 
(三)利用开发工具的支持。 
许多数据库开发工具都有一些方便的选项或部件来支持并发控制,而不论DBMS是否支持并发控制。我们看一下Delphi与Powerbuilder的并发控制方法。 
Delphi是一个优秀的c/s开发工具,它用来查询数据的数据库控件是TQuery,它可以和TUpdatesql控件有机的结合起来完成数据库表数据的浏览和更新。其中在TQuery控件中有一个属性是Updatemod(修改模式),他有三种选择:(1)upWhereAll:在浏览和修改期间只要有人修改了此记录某个列,那么不管你是否修改过这个列,你的修改在提交时都不能成功。(2)upWhereChanged:只根据键值列和你已经修改的列来决定你的修改是否成功,如果别人所修改的本记录的列与你修改的列不相交,那么你的修改仍然是成功的。(3)UpWhereOnly:只根据键值是否修改来判断你的更新是否成功。 
与TQuery控件配套使用的TUpdatesql控件根据所指定的修改属性,自动生成所需的更新语句,非常方便。第2种模式是最常用的修改模式,只要别人对记录所做的修改不与自己的重合,那么就会提交成功,这即保证不会发生数据的丢失、覆盖,并且具有较高的并发度。还是上边的例子,比如说客户浏览记录后修改的是记录中Mpayout、Mbalance两列,那么在修改选项upWhereChanged下,Tupdatesql控件所生成的SQL语句是: 
UPDATE acount SET (Mpayout,Mbalance)=($Mpayout,$Mbalance)  
WHERE Key=Key_old and Mpayout=Mpayout_old and Mbalance=Mbalance_old; 
其中Key_old,Mpayout_old和Mbalance_old是delphi替用户所生成的中间变量,暂存原先数据记录的旧值,用于比较旧值与现在的值是否相等,如果不相等,说明已经有别的用户更改了该记录,那么为了避免丢失修改,该用户的更新操作不能完成,反之则可以完成。那么当出纳员修改帐户时,如果别人已经修改了这个帐户,那么他的这次修改是不成功的,必须重新刷新记录才可能成功修改。对上面的例子进行这种改造,就可以避免银行的损失。 
与Delphi媲美的一个另一个工具是著名的Powerbuilder,在其DataWindows的设计中,我们选择菜单Rows|Update…,会出现Specify Update Characteristics的设置窗口,在这个窗口中我们设置Update语句中Where子句的生成,以此来进行并发控制。在这里有三个选项: (1)Key Columns:生成的Where子句中只比较表中的主键列的值与最初查询时是否相同来确定要修改的记录。与Delphi中的UpWhereOnly选项对应。 (2)Key and Updateable Columns:生成的Where子句比较表中主键列和可修改列的值与最初查询时否是相同。与Delphi的upWhereall相对应。 (3)Key and Modified Columns:与Delphi的upWhereChanged选项对应。Where子句比较主键和要修改的列。  
(四)调整应用。 
有的数据库没有提供并发控制的功能,例如Foxpro等,象Mysql的某些版本也不支持事务。而且有的开发工具(例如一些网页脚本编辑器等)也没有提供实现并发控制的部件,那么要实现并发控制,就只能借助于调整我们的应用程序和数据库结构的办法了。 
可以按照封锁的基本思想来调整应用。在需要进行并发控制的数据库表中增加一个锁字段,这个字段可以是一个布尔型变量,为true则为锁定,为false则为空闲。此时表的结构变为: 
列名称  列代码  列类型 
帐户号  Id(键值列) Char(10) 
户主  Uname Char(10) 
存入金额  Mdeposit  Currency 
支出金额 Mpayout  Currency  
存款余额  Mbalance Currency 
锁  Lock  Boolean 
如果一个应用中,客户查询这个表时,可以修改表的记录,那么为了防止别的客户在该用户编辑某记录期间修改这个记录,那么就需要客户在浏览到该记录的数据时,给该记录加上锁(即将锁字段改为true),修改完毕后释放锁(将锁字段改为false)。别的客户要修改这个表的记录的话就先检测一下该记录有没有被加锁,如果已经加锁,则不能进行修改。如果锁字段空闲,那么首先给该记录加锁,然后取记录给客户浏览、编辑,在此期间别的客户不能修改记录。这就很有效的防止了丢失修改。 
上面是一种常用的方法,但是也不是完全没有缺点,它可能会产生这样一种副作用:当一个用户决定修改一个记录时,该记录被锁定,等待用户修改,但此时正好用户离开了,那么这条记录将一直被锁定直到用户提交(可能是几个小时之后了)或者会话超时,那么在这一段时间内别的用户就不可以更改这一条记录,导致并发度很低。有一个绕过这个问题的解决办法就是将浏览到的记录记到old_record(自定义的变量)中,再将old_record的内容拷贝到一个新记录new_record(自定义的变量)中,用户编辑new_record,当提交new_record时比较old_record和原先的记录,如果不一样,则表明已经有用户修改了原先的记录,此时把对new_record做的修改放弃;反之则将其内容提交。 
上边的方法还有一个小小的不足:在做新旧记录的比较的时候必须比较整条记录,费时间而且程序写起来比较麻烦。可以考虑在原先的表中增添一个时间戳列(此时可以取消lock列),那么此时表的结构变为: 
列名称  列代码  列类型 
帐户号  Id(键值列) Char(10) 
户主  Uname Char(10) 
存入金额  Mdeposit  Currency 
支出金额 Mpayout  Currency  
存款余额  Mbalance Currency 
时间戳  Date  Datetime 
当浏览记录时将时间戳值记到old_date(自定义变量)中,再将记录内容记到一个新记录new_record中,用户编辑new_record,当提交new_record时比较old_date和原先的记录中的时间戳,如果不一样,则表明已经有用户修改了原先的记录,此时把对new_record做的修改放弃;反之则将其内容提交。更新语句为: 
UPDATE acount SET (Mpayout,Mbalance,Date)=($Mpayout,$Mbalance,$Date)  
WHERE Key=Key_old and Date=$Date_old; 
五.总结 
我们通常说的并发控制是指在DBMS(数据库管理系统)内部进行的并发控制。而并发控制的方法非常丰富,远不止此。可以借助于数据库本身的能力,也可以利用开发工具,还可以通过调整自己的程序来实现。在数据库应用中,进行并发控制的方法、实现途径多种多样。在选择时所依据的基本原则就是:数据一致性一定要合乎应用的需要,在此基础上,尽量提高并发度。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -