Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 347|回复: 0

访问数据库时如何解决并发问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-12 13:38:36 | 显示全部楼层 |阅读模式
    在数据库访问时。如果处理并发访问的问题
    或者当一个操作员对一个对象作读操作时。另一个操作员对此对象作写操作的时候
    如何避免死锁发生

    /**********  加锁   ***************
    设table1(A,B,C)
    A    B    C
    a1   b1   c1
    a2   b2   c2
    a3   b3   c3

    1)排它锁
    新建两个连接
    在第一个连接中执行以下语句
    begin tran
       update table1
       set A='aa'
       where B='b2'
       waitfor delay '00:00:30'  --等待30秒
    commit tran
    在第二个连接中执行以下语句
    begin tran
       select * from table1
       where B='b2'
    commit tran

    若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待30秒

    2)共享锁
    在第一个连接中执行以下语句
    begin tran
       select * from table1 holdlock -holdlock人为加锁
       where B='b2'
       waitfor delay '00:00:30'  --等待30秒
    commit tran

    在第二个连接中执行以下语句
    begin tran
       select A,C from table1
       where B='b2'
       update table1
       set A='aa'
       where B='b2'
    commit tran

    若同时执行上述两个语句,则第二个连接中的select查询可以执行
    而update必须等待第一个连接中的共享锁结束后才能执行 即要等待30秒

    3)死锁
    增设table2(D,E)
    D    E
    d1   e1
    d2   e2
    在第一个连接中执行以下语句
    begin tran
       update table1
       set A='aa'
       where B='b2'
       waitfor  delay '00:00:30'
       update table2
       set D='d5'
       where E='e1'
    commit tran

    在第二个连接中执行以下语句
    begin tran
       update table2
       set D='d5'
       where E='e1'
       waitfor  delay '00:00:10'
       update table1
       set A='aa'
       where B='b2'
    commit tran

    同时执行,系统会检测出死锁,并中止进程
    --------------------------------------------------------------
    SET IMPLICIT_TRANSACTIONS  ON --用户每次必须显式提交或回滚。否则当用户断开连接时,
                                  --事务及其所包含的所有数据更改将回滚

    SET IMPLICIT_TRANSACTIONS  OFF --自动提交模式。在自动提交模式下,如果各个语句成功
                                   --完成则提交。




    1:如上

    2: 如何锁一个表的某一行


    A 连接中执行

    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

    begin tran

    select * from tablename with (rowlock) where id=3

    waitfor delay '00:00:05'

    commit tran

    B连接中如果执行

    update tablename set colname='10' where id=3 --则要等待5秒

    update tablename set colname='10' where id<>3 --可立即执行

    2 锁定数据库的一个表

    SELECT * FROM table WITH (HOLDLOCK)


    注意: 锁定数据库的一个表的区别

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

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


    SELECT 语句中“加锁选项”的功能说明
      SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能。用户既能使用SQL Server的缺省设置也可以在select 语句中使用“加锁选项”来实现预期的效果。 本文介绍了SELECT语句中的各项“加锁选项”以及相应的功能说明。
      功能说明: 
      NOLOCK(不加锁)
      此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或回滚(Roll Back)中的数据, 即所谓的“脏数据”。

      HOLDLOCK(保持锁)
      此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。

      UPDLOCK(修改锁)
      此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。

      TABLOCK(表锁)
      此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。

      PAGLOCK(页锁)
      此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。

      TABLOCKX(排它表锁)
      此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。


    --或者自己加锁(控制更灵活)

    --锁定记录,只允许单用户修改的例子:

    --创建测试环境
    --创建测试表--部门表
    create table 部门(departmentid int,name varchar(10))

    --记录锁定表
    create table lock(departmentid int,dt datetime)

    go
    --因为函数中不可以用getdate,所以用个视图,得到当前时间
    create view v_getdate as select dt=getdate()
    go
    --创建自定义函数,判断记录是否锁定
    create function f_chk(@departmentid int)
    returns bit
    as
    begin
    declare @re bit,@dt datetime
    select @dt=dt from v_getdate
    if exists(select 1 from lock where departmentid=@departmentid
    and datediff(ss,dt,@dt)<5)
    set @re=1
    else
    set @re=0
    return(@re)
    end
    go

    --数据处理测试
    if dbo.f_chk(3)=1
    print '记录被锁定'
    else
    begin
    --也可以是查询
    begin tran
    insert into lock values(3,getdate())
    update 部门 set name='A' where departmentid=3
    delete from lock where departmentid=3
    commit tran
    end

    --删除测试环境
    drop table 部门
    drop view v_getdate
    drop function f_chk

    如果是死锁可以查一下:
    1:sp_who 或 sp_who2
    2: Select * from sysprocesses where blocked <> 0
    3: 企业管理器->服务器->管理工具->活动->当前活动 然后把他kill掉。。。
       进程信息中,如果发现旁边有一个锁状的图标,就表明这个进程是死锁,kill掉
    4:SQL事件探查器,监控一下,看主要是那些处理引起的死锁.然后做相应的处理.
    用事件探查器new一个trace,监视一下造成你sqlserver停顿的情况。。。
    
    最好的办法还是检查一下引起锁的原因,一般是由你的代码引起的。
    

    经过根踪调试。我发现问题如下:
    1。当一个操作对一张表进行读操作的时候。这时如果另一个表进行读操作没有问题。如果
    另一个操作对这个表进行写操作的时候。就会出现这样的情况。在单击保存时。会持续等。
    只有另一个读操作的程序。退出读表的界面。这个就会保存成功。
    2。如果把同样的环境改到我的笔记本上没有这个问题。如果再放到IBM服务器上就会出现上述所讲的问题。

    现有疑问如下:
    1。为何笔记本做服务(P41。8CPU。256M)没有问题。面用IBM做服务器有问题?
    2。如果我把SQLCA。AUTOCOMMIT=FALSE改为SQLCA。AUTOCOMMIT=TRUE。这个问题就不存在了。但是我想这只是从表面上解决了这个问题。没有从根上解决这个问题。
    3。如果是多个工作站。一台用SQLCA。AUTOCOMMIT=TRUE,另一台AUTOCOMMIT=FALSE会有问题吗。?如果我想进行ROLLBACK操作会有问题吗?
    4。如果在同一个网段上有两个SQLSERVER2000服务器会有影响吗?

     
    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-16 01:49 , Processed in 0.068818 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表