sql 锁相关(转)

      锁是数据库中的一个很是重要的概念,它主要用于多用户环境下保证数据库完整性和一致性。 咱们知道,多个用户可以同时操纵同一个数据库中的数据,会发生数据不一致现象。即若是没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。这些问题包括:丢失更新、脏读、不可重复读和幻觉读:mysql


1.当两个或多个事务选择同一行,而后基于最初选定的值更新该行时,会发生丢失更新问题。每一个事务都不知道其它事务的存在。最后的更新将重写由其它事务所作的更新,这将致使数据丢失。例如,两个编辑人员制做了同一文档的电子复本。每一个编辑人员独立地更改其复本,而后保存更改后的复本,这样就覆盖了原始文档。最后保存其更改复本的编辑人员覆盖了第一个编辑人员所作的更改。若是在第一个编辑人员完成以后第二个编辑人员才能进行更改,则能够避免该问题。sql


2. 脏读就是指当一个事务正在访问数据,而且对数据进行了修改,而这种修改尚未提交到数据库中,这时,另一个事务也访问这个数据,而后使用了这个数据。由于这个数据是尚未提交的数据,那么另一个事务读到的这个数据是脏数据,依据脏数据所作的操做多是不正确的。例如,一个编辑人员正在更改电子文档。在更改过程当中,另外一个编辑人员复制了该文档(该复本包含到目前为止所作的所有更改)并将其分发给预期的用户。此后,第一个编辑人员认为目前所作的更改是错误的,因而删除了所作的编辑并保存了文档。分发给用户的文档包含再也不存在的编辑内容,而且这些编辑内容应认为从未存在过。若是在第一个编辑人员肯定最终更改前任何人都不能读取更改的文档,则能够避免该问题。数据库


3.不可重复读是指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,因为第二个事务的修改,那么第一个事务两次读到的的数据多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,做者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。若是只有在做者所有完成编写后编辑人员才能够读取文档,则能够避免该问题。并发

 
4.幻觉读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的所有数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样。例如,一个编辑人员更改做者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现做者已将未编辑的新材料添加到该文档中。若是在编辑人员和生产部门完成对原始文档的处理以前,任何人都不能将新材料添加到文档中,则能够避免该问题。fetch


      因此,处理多用户并发访问的方法是加锁。锁是防止其余事务访问指定的资源控制、实现并发控制的一种主要手段。当一个用户锁住数据库中的某个对象时,其余用户就不能再访问该对象。加锁对并发访问的影响体如今锁的粒度上。为了控制锁定的资源,应该首先了解系统的空间管理。在SQL Server 2000系统中,最小的空间管理单位是页,一个页有8K。全部的数据、日志、索引都存放在页上。另外,使用页有一个限制,这就是表中的一行数据必须在同一个页上,不能跨页。页上面的空间管理单位是盘区,一个盘区是8个连续的页。表和索引的最小占用单位是盘区。数据库是由一个或者多个表或者索引组成,便是由多个this

 

 

SQL语句:日志

LOCK TABLES tablename WRITE;
LOCK TABLES tablename READ;
INSERT INTO assignment VALUES (1,7513,'0000-00-00',5),(1,7513,'2003-01-20',8.5);
UNLOCK TABLES;对象

对于多个用户同时提交表单,而且同时向数据库中获得表单ID,我是这样解决的:索引

mysql_query("lock tables po read");
mysql_query("lock tables po write");事务

mysql_query("update po set id=id +1"));// increase po id

$sql = "SELECT id FROM po";
$result = mysql_query($sql);
if ($row = mysql_fetch_assoc($result)) {
    echo $row["id"]; // this order will use this id
}

mysql_free_result($result);
mysql_query("unlock tables");

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

帮忙看看如何在这段代码先后给数据库写加锁和解锁语句

'(在这里给数据库加锁,如何写加锁语句?) 
       ............... 
       i = str(从记录集rst0中获得最大入库单号) 
       '若不加锁,在这容易形成并发冲突。由于在申请到最大入库单号以后尚未来得及创建实际记录,其它客户端可能也申请到了一样的入库单号 
       .............. 
       rst.open "select * from 入库 where 入库单号= " + i + " and 商品ID=0 ", cn, adOpenStatic, adLockOptimistic 
       If rst.RecordCount = 0 Then 下一个入库单号 = i + 1 
       ............... 
       '(在这里给数据库解锁,如何写解锁语句?)

解答1:先将须要加锁执行的语句声明成一个事务(如2楼),而后加锁,SQL Server中锁的类型不少,看你须要加哪一种类型的锁: 
HOLDLOCK 将共享锁保留到事务完成,而不是在相应的表、行或数据页再也不须要时就当即释放锁。HOLDLOCK 等同于 SERIALIZABLE。 
NOLOCK    不要发出共享锁,而且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 SELECT 语句。 
PAGLOCK    在一般使用单个表锁的地方采用页锁。 
READCOMMITTED 用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认状况下,SQL Server 2000 在此隔离级别上操做。 
READPAST 跳过锁定行。此选项致使事务跳过由其它事务锁定的行(这些行日常会显示在结果集内),而不是阻塞该事务,使其等待其它事务释放在这些行上的锁。 READPAST 锁提示仅适用于运行在提交读隔离级别的事务,而且只在行级锁以后读取。仅适用于 SELECT 语句。 
READUNCOMMITTED 等同于 NOLOCK。 
REPEATABLEREAD 用与运行在可重复读隔离级别的事务相同的锁语义执行扫描。    
ROWLOCK 使用行级锁,而不使用粒度更粗的页级锁和表级锁。 
SERIALIZABLE 用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。 
TABLOCK 使用表锁代替粒度更细的行级锁或页级锁。在语句结束前,SQL Server 一直持有该锁。可是,若是同时指定 HOLDLOCK,那么在事务结束以前,锁将被一直持有。 
TABLOCKX    使用表的排它锁。该锁能够防止其它事务读取或更新表,并在语句或事务结束前一直持有。 
UPDLOCK    读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优势是容许您读取数据(不阻塞其它事务)并在之后更新数据,同时确保自从上次读取数据后数据没有被更改。 
XLOCK 使用排它锁并一直保持到由语句处理的全部数据上的事务结束时。可使用 PAGLOCK 或 TABLOCK 指定该锁,这种状况下排它锁适用于适当级别的粒度。

解答2”要使一表在整个处理过程当中不会被并发修改可用事务begin transelect * from 表名 with HOLDLOCK  --处理语句....................commit tran加了 with holdlock后,在事务提交以前,别人动不了你的表。。。。。。。。。。。。。。。。。。。。。。。。。。。。

相关文章
相关标签/搜索