• 十、锁


    十、锁

    锁的目的是为了解决并发

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

    一、程序锁

    二、数据库锁

    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将只能等待

  • 相关阅读:
    从技术演变的角度看互联网后台架构
    设计模式的六大原则
    Xinetd服务的安装与配置详解
    linux route详细解读
    Linux信号处理
    Go语言的成功也预示着Rust的成功【转】
    Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    C#代码覆盖率实践-vsinstr和OpenCover
    MYSQL企业常用架构与调优经验分享
    StrongLoop
  • 原文地址:https://www.cnblogs.com/fger/p/11113148.html
Copyright © 2020-2023  润新知