第11章网络数据共享(1)共享VFP中数据库及其表是存放数据的主要容器,还有操作这些数据库的程序和其他各种文件。实现共享的方法有两种:一种方法是将数据从本地硬盘移到网络中一台文件服务器计算机中,每个用户都可以访问它。另一个方法是使本地硬盘或存放这些文件的文件夹共享。(2)冲突数据处理中的一个基本问题就是如何解决两个以上用户同时试图修改数据时所产生的冲突。认为最后保存修改的用户才能真正地修改数据。(3)锁定VFP提供了在多用户环境中记录和表锁定函数、命令以及新的数据缓冲方案。当有多个用户要求访问表和记录时,锁就会禁止其他用户进入该数据区域,直到当前占用数据的用户完成他的编辑活动并安全地退出操作区域为止。而使用缓冲可以保存原始记录,这样在必要时可以恢复这些记录。在VFP的文件共享环境中,数据库必须存储在网络驱动器中以便用户共享。(4)死锁当一个用户锁定了一条记录或一个表,又试图锁定另一条记录或另一个表,但这一记录或表格已经为另一个用户锁定,而这个用户也在试图锁定第一个用户已锁定的记录。结果两个用户均被“挂起”以等待对方释放锁定的记录,很明显,谁都不会获得所需的全部资源从而完成自己的任务,所以谁也不可能释放锁定的记录。这就是共享环境中经常发生的死锁。第11章网络数据共享11.1记录锁定11.2数据会话11.3数据缓冲11.4事务处理11.1记录锁定1.记录锁定和文件锁定多用户访问的应用程序中,只有那些真正需要它的用户才能获得访问权限。当正确地使用了记录锁定时,它便只允许执行记录锁定操作的用户写该记录。对于文件锁定来说,它将锁定整个表,禁止其他所有用户向表中写入数据,只允许编辑表格中的任何记录。注意,记录锁定和文件锁定并不禁止其他用户从被锁定的记录和表中读取数据。应尽力使用记录锁定,因为记录锁定只会禁止对单个记录的访问,不会影响整个表格。当一个用户在编辑XSCJ数据库的XS表中的第30条记录时,另一个用户可以同时编辑该表中的第20条记录,而这两个用户可以各自保存自己的修改而不会影响对方。当加锁用户解锁从锁定状态释放锁,其他用户才能对刚加锁表或记录进行修改操作或再锁定。2.自动锁定与手工锁定记录锁定和文件锁定既可以自动锁定,也可以手工锁定。当使用特定的数据更新命令时,VFP会试图自动锁定记录。11.1记录锁定当这些命令执行结束后,系统将自动释放所建立的锁定。例如SETEXCLUSIVEOFFOPENDATABASEXSCJUSEXS1APPENDFROMXSFORXH=”02”APPENDFORM命令会自动锁定整个XS1表,将另一个文件中的数据加入表格试图锁定整个表格,当添加任务结束后,APPEND命令将释放所建立的锁定。设置SETEXCLUSIVEOFF,允许网络上的任何用户共享和修改网络上打开的表;USE命名打开表时带EXCLUSIVE参数是以独占方式打开表。命令INSERT,INSERTBLANK,MODIFYSTRUCTURE,PACK,REINDEX和ZAP在独占方式打开时执行。VFP还提供了一系列锁定函数用于手工锁定记录。手工锁定函数将测试记录或表的锁定状态。手工锁定函数为LOCK()、RLOCK()和FLOCK()函数。RLOCK()和LOCK()函数等价,都用于锁定单个记录或一组记录。格式:LOCK([工作区号|表别名]|[记录号表,工作区号|表别名])格式:RLOCK([工作区号|表别名]|[记录号表,工作区号|表别名])11.1记录锁定选[工作区号|表别名]为锁定指定工作区或表的当前记录。无参数,则锁定当前表的当前记录。选[记录号表,工作区号|表别名],则可以锁定多条记录,锁定的多条记录由记录号表指定,此时工作区号|表别名不能省略。能否用LOCK()或RLOCK()同时锁定多条记录,还必须SETMULTILOCKSON。函数锁定成功返回.T.,否则返回.F.。FLOCK()函数用于锁定整个文件。格式:FLOCK([工作区号|表别名])选[工作区号|表别名]为锁定指定工作区的表或表别名指定的表。无参数,则锁定当前表。函数锁定成功返回.T.,否则返回.F.。可用下列命令设定LOCK()、RLOCK()和FLOCK()函数尝试加锁的次数和时间,不致于当加锁不成功时就立即返回(返回值为.F.)。格式:SETREPROCESSTOn[SECONDS]|TOAUTOMATIC选SECONDS,则n为秒。选TOAUTOMATIC或n=0(默认值),则系统会对表或无限次对表或记录加锁。此前如设置SETSTATUSON,系统在尝试记录加锁时系统会显示提示信息,此时用户可按ESC键取消加锁尝试。若n=1,则用户不可按ESC键取消加锁尝试。还可参考SYS(3051)和SYS(3052)函数。如果用LOCK()、RLOCK()和FLOCK()函数锁定一条记录或一个表,那么在完成任务后应立即用UNLOCK命令释放锁定。格式:UNLOCK[RECORD记录号][IN工作区号|表别名][ALL]11.1记录锁定记录号0,则解除该记录的锁定,记录号=0,则解除由RLOCK(0)或LOCK(0)锁定的表头。在UNLOCKRECORD记录号时会解除表的文件锁。不带任何参数的UNLOCK命令,将解除当前表的所有锁,UNLOCKALL将解除当前所有打开的表的所有锁,只有开锁后,其他用户才可能操作这些锁定的记录和表。【例Ex_Lock】手工加锁执行REPLACE…FOR命令操作XSCJ数据库XS表。SETEXCLUSIVEOFFSETREPROCESSTO0OPENDATABASEXSCJUSEXSIFFLOCK()REPLACEJSJWITH200FORZXF30UNLOCKElSEWAIT“表已经被别人上锁!”WINDOWNOWAITENDIF11.1记录锁定【例Ex_LReplace】手工加锁执行REPLACE命令操作XSCJ数据库XS表的3个记录。SETEXCLUSIVEOFFSETREPROCESSTO0SETMULTILOCKSONUSEXSIFRLOCK(“2,10,16”,”XS”)GOTO2REPLACEJSJWITH200GOTO10REPLACEJSJWITH200GOTO16REPLACEJSJWITH200UNLOCKELSEWAIT“表已经被别人上锁!”WINDOWNOWAITNOWAITENDIF11.1记录锁定如果无法获得列表中的任何记录,那么任何记录都不会被锁定。注意,更新一个表格中的多条记录,锁定整个表格要比锁定多条记录方便得多。这一锁定必须在更新过程中均有效,不是编辑会话的整个过程。如果可能,最好使用只锁定单个记录的命令,不要过多地使用试图锁定整个表格的命令。因为:由文件锁定而带来的网络开销以及其他用户不能锁定该文件的可能性。在VFP中,只有当文件中的所有记录均未被用户锁定时,该文件才能被锁定。而在多用户应用程序中,这可能要等待很久。在许多情况下,从一条记录或表向另一条记录或另一个表的物理移动会促使FoxPro自动释放临时锁定的项目。然而,如果显式地锁定了一个表或一条记录,那么其他用户只有等待该表格的锁定被释放后才能使用它。执行表11.1的命令后,将释放记录和表锁。如果SETMULTILOCKSOFF,在用户自定义的函数(UDF)中锁定了一条记录,则将记录指针移开后再将指针移回当前记录,那么该记录上的锁定将被自动释放。如果使用Browse、Change、Edit或者ModifyMemo等命令来编辑记录时,将会发现只有当开始进行编辑时,这些命令才会锁定记录。11.1记录锁定当编辑表的字段时,相关的记录会被锁定以防止双重编辑。如果当前记录或者任何一个相关的记录已经被另一个用户锁定,那么锁定操作会失败。只有当成功地锁定记录时,FoxPro才会允许用户编辑记录。当用户转换到下一条记录,或者激活另一窗口或者执行其他任务时,锁定被系统释放。11.2数据会话VFP数据会话(DataSession)是附属于表单上的数据环境,可以把表附着到一个使用这些表的表单上。数据会话分为两类:私有的和缺省的。数据会话允许对一个表单建立多个实例。Form.DataSession属性可以被设置为1或2。使用缺省值1时,对表单的修改将可以反映到表单的所有其他打开的实例中。将属性设置为2(私有数据会话)时,在表单中的任何修改将不会自动反映到同一表单的大小其他实例中。用户能够打开的会话个数仅仅由系统内存大小及磁盘空间决定。如果要从表单设计器中开始多个数据会话,可以将DataSession属性设置为2,或者也可以在命令窗口输入命令SETDataSessionTO2。当将DataSession属性设置为2时,VFP为表单的每个实例建立一个新的数据会话,表单的每个实例维持单独的一些数据,其中包括一系列单独的锁定。11.2数据会话打开数目主要取决于RAM的大小及硬盘空间,通过LoadEvent代码中的命令来修改会话说明,用户可以从View窗口中观察到数据会话的内容。每个数据会话都被顺序编号,并且用名为DataSessionlD的数据会话标号来标识。表单的DataSessionID属性可被显示出来:DOFORMForm1?Form1.DataSessionIDDOFORM2Form1Nameone?one.DataSessionID用户尽量避免改动表单的数据会话标号,一旦修改了数据会话标号,与数据绑定的控件便会失去它们的数据源。如果用户希望表单的数据环境(DataEnvironment)一直有效且保持不变,那么可以使用表单设计器(FormDesigner)中的数据环境对话框。虽然表单的所有实例均可访问同一数据,并且将对其修改立即反映到所有表单的公用数据中,但可以用数据环境(DataEnvironment)属性表格中的重构属性改变自动数据会话分配。11.3数据缓冲VFP引入的数据缓冲使在网络中对数据的保护比显式锁定更加容易。缓冲数据的使用能够更好地使用本地资源,限制了对网络及服务器资源的竞争。缓冲数据在工作站的内存中保存了用户对数据所做的一切修改。只有当应用程序要求VFP进行更新时,服务器中的数据才会更新。实现数据缓冲思想的显式锁定方案实现步骤如下:(1)当要修改的记录时,执行SCATTERMEMVAR命令将所有字段存入内存变量。(2)修改内存变量中的数据,而不是表中的数据。(3)如果对所作的修改感到满意,可以用GATHERMEMVAR命令保存修改。如果希望恢复数据,则可以再次执行SCATTERMEMVAR命令来覆盖内存变量中的数据。VFP提供了两种缓冲方案:记录缓冲和表格缓冲。(1)记录缓冲记录缓冲(recordbuffering)对单个记录的编辑进行缓冲。一旦完成对单个记录的修改后,数据便立即写入磁盘。这一写入动作发生在记录指针移动时,或者执行TABLEUPDATE()函数时。11.3数据缓冲(2)表格缓冲表缓冲(tablebuffering)把对表的多处修改存入内存。关闭表格时或者使用了ROWS参数设为.T.的TABLEUPDATE()函数时,数据便会写入磁盘。该方法适用于一个表格中的记录或者一对多关系中的子记录。在多用户环境中,编辑、删除及修改单条记录或者多条记录时,这种缓冲方式提供了数据更新和数据维护方面的安全保证。利用VFP的缓冲技术,用户不必再将数据赋给内存变量;用户可以直接编辑字段,因为只要不执行TABLEUPDATE(),原始数据总是安全的。利用缓冲技术可以检测和消除数据更新操作的冲突。在编辑过程中,当前记录被复制到已由VFP标识并管理的内存或者磁盘中,当前用户操作的数据被安全地隔离开,所以其他用户依然可以访问原始记录。当记录被写回表格时,FoxPro便试图锁定该记录,并检查是否有其他用户做的修改,其最终的修改将被写入硬盘。11.3数据缓冲1.锁定缓冲区记录缓冲和表格缓冲可以用于两种不同的锁定模式。这些模式决定了在何种条件下锁定一条或多条记录,以及如何和何时释放这些记录。这两种模式称为悲观锁定(pessimisticlocking)