1.在cs数据库中,例如类似售票系统之类,有多个客户端连接,如果都要同时对某一数据记录进行操作,修改或者删除,如何保证数据得互斥操作,?保证数据得正确性?数据库采用得是sqlserver.2是否利用事务得方法就可以控制互斥操作了,但比如这样: 现在还剩下1张票,a,b,c
都要这张票,然后假设都同时向服务器提出申请,如何实时地检测当前得售票情况呢,
如果服务器都接受得话,那明显会出错.!
3.不知道各位高手在处理这类数据库得时候有什么经验,可以介绍一下.
   小弟学习. 多谢.

解决方案 »

  1.   

    1 用锁!详情看help
    2 存储过程事务进行操作时,系统会自动分析所需的操作对象、从而选取相应的锁。
    3 一般对于dbms,不是互斥的问题,因为dbms会自动添加的,除非你有自己的想法,可以用于句修改自己的锁类型,我觉得关键反而是因为锁引起的死锁情况,设计是需要考虑)。
      

  2.   

    SQL Server 中的锁定介绍
    Microsoft® SQL Server™ 2000 具有多粒度锁定,允许一个事务锁定不同类型的资源。为了使锁定的成本减至最少,SQL Server 自动将资源锁定在适合任务的级别。锁定在较小的粒度(例如行)可以增加并发但需要较大的开销,因为如果锁定了许多行,则需要控制更多的锁。锁定在较大的粒度(例如表)就并发而言是相当昂贵的,因为锁定整个表限制了其它事务对表中任意部分进行访问,但要求的开销较低,因为需要维护的锁较少。SQL Server 可以锁定以下资源(按粒度增加的顺序列出)。资源 描述 
    RID 行标识符。用于单独锁定表中的一行。 
    键 索引中的行锁。用于保护可串行事务中的键范围。 
    页 8 千字节 (KB) 的数据页或索引页。 
    扩展盘区 相邻的八个数据页或索引页构成的一组。 
    表 包括所有数据和索引在内的整个表。 
    DB 数据库。 
    SQL Server 使用不同的锁模式锁定资源,这些锁模式确定了并发事务访问资源的方式。SQL Server 使用以下资源锁模式。锁模式 描述 
    共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。 
    更新 (U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。 
    排它 (X) 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时对同一资源进行多重更新。 
    意向 用于建立锁的层次结构。意向锁的类型为:意向共享 (IS)、意向排它 (IX) 以及与意向排它共享 (SIX)。 
    架构 在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改 (Sch-M) 和架构稳定性 (Sch-S)。 
    大容量更新 (BU) 向表中大容量复制数据并指定了 TABLOCK 提示时使用。 
    共享锁
    共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。一旦已经读取数据,便立即释放资源上的共享 (S) 锁,除非将事务隔离级别设置为可重复读或更高级别,或者在事务生存周期内用锁定提示保留共享 (S) 锁。更新锁
    更新 (U) 锁可以防止通常形式的死锁。一般更新模式由一个事务组成,此事务读取记录,获取资源(页或行)的共享 (S) 锁,然后修改行,此操作要求锁转换为排它 (X) 锁。如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为排它 (X) 锁。共享模式到排它锁的转换必须等待一段时间,因为一个事务的排它锁与其它事务的共享模式锁不兼容;发生锁等待。第二个事务试图获取排它 (X) 锁以进行更新。由于两个事务都要转换为排它 (X) 锁,并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。若要避免这种潜在的死锁问题,请使用更新 (U) 锁。一次只有一个事务可以获得资源的更新 (U) 锁。如果事务修改资源,则更新 (U) 锁转换为排它 (X) 锁。否则,锁转换为共享锁。排它锁
    排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据。意向锁
    意向锁表示 SQL Server 需要在层次结构中的某些底层资源上获取共享 (S) 锁或排它 (X) 锁。例如,放置在表级的共享意向锁表示事务打算在表中的页或行上放置共享 (S) 锁。在表级设置意向锁可防止另一个事务随后在包含那一页的表上获取排它 (X) 锁。意向锁可以提高性能,因为 SQL Server 仅在表级检查意向锁来确定事务是否可以安全地获取该表上的锁。而无须检查表中的每行或每页上的锁以确定事务是否可以锁定整个表。意向锁包括意向共享 (IS)、意向排它 (IX) 以及与意向排它共享 (SIX)。锁模式 描述 
    意向共享 (IS) 通过在各资源上放置 S 锁,表明事务的意向是读取层次结构中的部分(而不是全部)底层资源。 
    意向排它 (IX) 通过在各资源上放置 X 锁,表明事务的意向是修改层次结构中的部分(而不是全部)底层资源。IX 是 IS 的超集。 
    与意向排它共享 (SIX) 通过在各资源上放置 IX 锁,表明事务的意向是读取层次结构中的全部底层资源并修改部分(而不是全部)底层资源。允许顶层资源上的并发 IS 锁。例如,表的 SIX 锁在表上放置一个 SIX 锁(允许并发 IS 锁),在当前所修改页上放置 IX 锁(在已修改行上放置 X 锁)。虽然每个资源在一段时间内只能有一个 SIX 锁,以防止其它事务对资源进行更新,但是其它事务可以通过获取表级的 IS 锁来读取层次结构中的底层资源。 
    架构锁
    执行表的数据定义语言 (DDL) 操作(例如添加列或除去表)时使用架构修改 (Sch-M) 锁。当编译查询时,使用架构稳定性 (Sch-S) 锁。架构稳定性 (Sch-S) 锁不阻塞任何事务锁,包括排它 (X) 锁。因此在编译查询时,其它事务(包括在表上有排它 (X) 锁的事务)都能继续运行。但不能在表上执行 DDL 操作。大容量更新锁
    当将数据大容量复制到表,且指定了 TABLOCK 提示或者使用 sp_tableoption 设置了 table lock on bulk 表选项时,将使用大容量更新 (BU) 锁。大容量更新 (BU) 锁允许进程将数据并发地大容量复制到同一表,同时防止其它不进行大容量复制数据的进程访问该表。
      

  3.   

    存储过程事务进行操作时,系统会自动分析所需的操作对象、从而选取相应的锁 ? 呵呵,不可能,事务和存储过程没关系
       这个问题就在于你希望得到这条记录的独占锁,这个其实完全取决于你的设计,比如,你先查票时,你select a from A , 这时你得到是他的共享锁,大家都能查到,关键在于你要票的过程,你在事务中update 你想要锁定的某条记录,此时你得到排它锁,其他人也不可能得到这条记录了,大忌是在事务中先 select 后update
      

  4.   

    用事务和隔离等级可达到你的要求:SET TRANSACTION ISOLATION LEVEL
    控制由连接发出的所有 Microsoft® SQL Server™ SELECT 语句的默认事务锁定行为。语法
    SET TRANSACTION ISOLATION LEVEL
        { READ COMMITTED
            | READ UNCOMMITTED
            | REPEATABLE READ
            | SERIALIZABLE 
        }参数
    READ COMMITTED指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或幻像数据。该选项是 SQL Server 的默认值。READ UNCOMMITTED执行脏读或 0 级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中或从数据集消失。该选项的作用与在事务内所有语句中的所有表上设置 NOLOCK 相同。这是四个隔离级别中限制最小的级别。REPEATABLE READ锁定查询中使用的所有数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据集,且幻像行包括在当前事务的后续读取中。因为并发低于默认隔离级别,所以应只在必要时才使用该选项。SERIALIZABLE在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这是四个隔离级别中限制最大的级别。因为并发级别较低,所以应只在必要时才使用该选项。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相同。注释
    一次只能设置这些选项中的一个,而且设置的选项将一直对那个连接保持有效,直到显式更改该选项为止。这是默认行为,除非在语句的 FROM 子句中在表级上指定优化选项。SET TRANSACTION ISOLATION LEVEL 的设置是在执行或运行时设置,而不是在分析时设置。示例
    下例为会话设置 TRANSACTION ISOLATION LEVEL。对于每个后续 Transact-SQL 语句,SQL Server 将所有共享锁一直控制到事务结束为止。SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
    GO
    BEGIN TRANSACTION
    SELECT * FROM publishers
    SELECT * FROM authors
    ...
    COMMIT TRANSACTION
    请参见调整事务隔离级别DBCC USEROPTIONS隔离级别SELECTSET©1988-2002 Microsoft Corporation. 保留所有权利。
      

  5.   

    看了大家的回复,三各问题其实都一样,我是这样做的
    先启动事务,然后锁定表(可用表锁,不要用页锁或行锁)
    如果实在不想管就直接用这样的update就可以锁定表
    adoconnection1.begintrans;
    try
      AdoQueryTemp.close;
      adoQueryTemp.clear;
      adoQueryTemp.sql.add('update tablename set columnname = columnname where columnname in(select max(columnname) from tablename);
      adoQueryTemp.execsql;
      下面队tablename进行操作
      adoconnection1.committrans;
    except
      adoconnection1.rollback;
    end;//tablename 为表名。columnname:为列名。
    //update后面的where语句不能去掉,否则在由写数据库无法锁定表。
      

  6.   

    绝对没有必要用表级锁...
    就是用后面用 with tablelock 也可以