sql语句对数据库表进行加锁和解锁

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

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

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

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

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

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

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 tran
select * from 表名 with HOLDLOCK
--处理语句
........
............

commit tran

加了 with holdlock后,在事务提交之前,别人动不了你的表

  

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

时间: 2024-10-14 13:52:24

sql语句对数据库表进行加锁和解锁的相关文章

sql语句查询数据库表结构信息

开发中经常用到查询指定表及其字段的信息,以下是我整理的SQL语句查询方法,供自己平时使用也提供给大家参考! 1.适用MS SQL SERVER: 1 SELECT 2 表名 = case when a.colorder=1 then d.name else '' end, 3 表说明 = case when a.colorder=1 then isnull(f.value,'') else '' end, 4 字段序号 = a.colorder, 5 字段名 = a.name, 6 标识 = c

sql语句 生成数据库表

  打开PowerDesigner,鼠标单击File菜单: 2 选择:Reverse Enginer,然后在他的子菜单选择Database...; 3 选择好DBMS(数据库管理系统)类型:然后点击确定按钮:这里演示选中的是mysql数据库,具体类型根据自己需要选择: 4 点击Add  Files 图标添加脚本: 5 找到要导入的sql脚本,鼠标单击打开按钮: 6 鼠标单击,确定按钮: 7 开始反向工程生成数据库..... 8 导入成功! 原文地址:https://www.cnblogs.com

通过SQL语句查看数据库表的列数

看具体是什么数据库,以oracle,mysql,sqlserver分别回答. 1.oracle: 1 select count(*) from user_tab_cols where table_name='表名';--表名含英文的话应为英文大写字母 结果如图: 2.mysql: 1 select count(*) from information_schema.COLUMNS where table_name='表名';--表名大小写均可 结果如图: 3.sqlserver: 1 select

使用SQL语句清空数据库所有表的数据

近来发现数据库过大,空间不足,因此打算将数据库的数据进行全面的清理,但表非常多,一张一张的清空,实在麻烦,因此就想利用SQL语句一次清空所有数据.找到了三种方法进行清空.使用的数据库为MS SQL SERVER.1.搜索出所有表名,构造为一条SQL语句 declare @trun_name varchar(8000)set @trun_name='' select @trun_name=@trun_name + 'truncate table ' + [name] + ' ' from syso

sql语句查询同一表内多字段同时重复的记录 sql数据库重复记录删除

分享下用sql语句删除数据库中重复记录的方法.比如现在有一人员表 (表名:peosons) 若想将姓名.身份证号.住址这三个字段完全相同的记录查询出来select p1.* from persons p1,persons p2 where p1.id<>p2.id and p1.cardid = p2.cardid and p1.pname = p2.pname and p1.address = p2.address可以实现上述效果.几个删除重复记录的SQL语句 1.用rowid方法2.用gr

关于oracle sql语句查询时表名和字段名要加双引号的问题

oracle初学者一般会遇到这个问题. 用navicat可视化创建了表,可是就是不能查到! 后来发现②语句可以查询到 ①select * from user; 但是,我们如果给user加上双引号就可以查到了! ②select * from "user"; 难道oracle跟mysql等不同,查询时候一定要加双引号?那这样不是很麻烦!于是经过查找资料得出如下结论: 1.oracle表和字段是有大小写的区别.oracle默认是大写,如果我们用双引号括起来的就区分大小写,如果没有,系统会自动

3,SQL语句及数据库优化

 1,统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的. 所以封装成复用方法,用标准模板来控制. select*from dual select*From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析.生成2个执行计划 2,不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长.一般来说这么复杂的语句通常都是有问题的.我拿着这2页长的SQL语句去请教原作者,结果他说

SQL语句及数据库优化

1,统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的. 所以封装成复用方法,用标准模板来控制. select*from dual select*From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析.生成2个执行计划 2,不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长.一般来说这么复杂的语句通常都是有问题的.我拿着这2页长的SQL语句去请教原作者,结果他说时

SQL语句创建数据库以及一些查询练习

--创建 MyCompany数据库 use master execute sp_configure 'show advanced options',1 --开启权限 reconfigure execute sp_configure 'xp_cmdshell',1 reconfigure execute xp_cmdshell 'mkdir e:\作业数据库'--自动创建文件夹 execute sp_configure 'xp_cmdshell',0--关闭权限,先关 reconfigure ex