十、锁

十、锁

锁的目的是为了解决并发

锁的层次来说有两种:程序锁、数据库锁.

一、程序锁

二、数据库锁

1、锁的场景

1、建一个表,主键唯一,一个系统处理业务,就往表里添加数据,现在连个业务系统ID是一致的,业务ID又是唯一的,以当一个系统添加数据时,另一个系统是无法往表中添加数据的。插入数据成功的系统就可以操作业务逻辑,插入失败的系统就不能操作执行业务逻辑了。这就实现了数据库锁。

 2、

T1:select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象)

T2: update table set column1=‘hello’

3、比如一个商品数量为1         业务一你查询耗时0.4毫秒更新耗费了0.6毫秒      业务二和业务一同一时间,也查询到商品数量为一耗时0.4毫秒的时候,然后,业务二也去更新    导致商品数量为负数了

(这种情况,查询和修改都不能分开,还必须放在一起,程序级分开的话,程序语句先执行查询,然后在修改,中间的间隔都会都会发生并发即程序执行查询操作共计0.4毫秒(其内程序运行耗时0.2毫秒,sql则也是0.2),修改操作共计则也是0.4(其内程序耗时0.2毫秒,sql则也是0.2)然后在程序修改的0.2内,业务2 查询也卡这里了)这也是 查询和修改不可以分开

写在一起的话,两种 一种是 sql 判断写在一个语句内,第二种 事务

sql查询不会用锁,但是修改的话, 比如 业务一查询0.2 业务二0.3 , 业务二执行查询0.2后又执行更新0.4毫秒,但是业务二执行查询0.3秒,而业务一更新0.4毫秒还没还没执行完。 

总结:锁尽量在sql 内,而sql  查询没必要使用锁,因为共享状态,而对语句的修改、添加、删除的的操作,又因为先查询,不能写在一个sql内,写在一个sql 也行就必须即有查询又有操作的语句进行单独加锁,而事务也是另一种处理展示(方便回滚,又方便关联多条查询语句,写法也是写在事务外部-如何语句的话会累死每一条拼的sql) 这也是 很多 事务与锁关键子多的原因。

 4、

--这种一句sql写的方法
if not exists(select * from Admin where id=1 AND PassWord='123465') --这个跟判断商品一样 判断商品编码 然后数量=0 是否存在,不存在就是可以减少更新操作
update Admin set remark='da' where id=1;

--这种一句sql 也不知道 有没有加锁,万一 我在sql 开两个窗口 写一个 循环呢,同时更新呢


--还不如事务的写法(也是一句sql,但是有区别会回滚、和锁写在外层,上面如果判断条件多的话,会很繁琐)当然事务也需要加锁

2、事务与锁关系

事务是用来操作处理插入多条数据一条失败,多条回滚。

锁则是多方操作一条,或者多方操作多条都场景下(即多条就涉及到事务),总结-两种1、锁-单行 2、事务与锁-多行(多行关系则用事务关联)

2、锁的使用

 数据库没有解锁的概念,只有不加锁的概念,语句如下:

NOLOCK(不加锁)
此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到

2、实践案例

一、示例一

--业务2查询数据

select * from Admin WITH (UPDLOCK) where Id=1 --sqlserver2008行锁

WAITFOR DELAY '00:00:01' --等待一秒后执行查询

--业务1执行更新操作 

update Admin set Remark='524wwwwww' where Id=1 WAITFOR DELAY '00:00:05' --耗时5秒后执行查询

----仅延迟执行,并不是耗时响应

一、示例二

第一步:在当前会话中锁定数据行。

--声明数据库引用
use testss;
go

--声明数据库行锁
begin tran tran1
select * from test1 with(rowlock,updlock) where id='1';
waitfor delay '00:00:10';
commit tran;
go

第二步:开启新会话,进行更新锁定数据行。

update test1 set sex='女' where id='1';

  

示例结果:事务延迟提交十秒,在事务未提交之前进行更新会发生进程阻塞,更新是失败的,事务提交完成后行锁被释放更新才能成功。

SELECT * FROM table WITH (HOLDLOCK) 其他事务/语句可以读取表,但不能更新删除

SELECT * FROM table WITH (TABLOCKX) 其他事务/语句不能读取表,更新和删除

例子:

begin tran
select * from test_table with (TABLOCKX) //表锁
commit tran

这时,其它语句,比如select * from test_table将只能等待

原文地址:https://www.cnblogs.com/fger/p/11113148.html