MS SQLSERVER2008的事务、锁、并发的问题

MS SQLSERVER2008的事务、锁、并发的问题,第1张

概述面是一个网友提出的非常好的问题: MS SQLSERVER2008的事务,锁,并发的问题 学习了SQL SERVER2008关于事务的讲解,关于锁的讲解,关于并发的理解。但是仍然有一些问题,不是很理解,希望大牛们给予指导。 问题1:并发访问的基础是多个外部进程,可以同时 *** 作同一张表,或者 *** 作同一个记录,总之是相同对象。这样带来的问题是,1、写覆盖,2、不可重复读,3、脏数据,4、幻数据。但是引入了

面是一个网友提出的非常好的问题:

MS sqlSERVER2008的事务,锁,并发的问题

学习了sql SERVER2008关于事务的讲解,关于锁的讲解,关于并发的理解。但是仍然有一些问题,不是很理解,希望大牛们给予指导。

问题1:并发访问的基础是多个外部进程,可以同时 *** 作同一张表,或者 *** 作同一个记录,总之是相同对象。这样带来的问题是,1、写覆盖,2、不可重复读,3、脏数据,4、幻数据。但是引入了锁以后,为什么锁就解决了上述问题哪?

问题2:比如说写覆盖,在有了共享锁以后,进程A,读取数据时,进程B不能够修改数据,那么进程A读取之后,进程B就可以修改数据了,但是发现进程A其实读到的,不还是错误数据吗?锁也没有解决问题呀?

问题3:关于死锁的问题,是不是说,死锁的发生,是因为两个进程在 *** 作数据时,编写的数据事务有错误,需要修改数据处理的事务,从而解决死锁的问题?还是说,死锁与使用编程的方式实现同步是两个层面的概念?编程解决死锁的问题,是用户在内存中共享数据的处理情况决定的,而数据库的同步是不需要编程的?


下面是我的回答:

1、为什么说,引入了锁之后,就能解决上面的问题呢?其实说到底,这个锁就是用来解决,当有多个并发进程访问同一个数据时,保持数据一致性的。此外,还有一个非常重要,但很多人都忽视的概念,那就是隔离级别的概念,这个隔离级别控制了,进程间相互影响的程度。

所以上面的4个问题,不仅需要锁,还是需要隔离级别来控制,才能得到解决。

sql server的隔离级别有4中:
read uncommitted  读未提交
read committed   读已提交
repeatable read  可重复读
serializable    串行化读

比如,在sql server中,任何一个进程在访问数据时,都会按照隔离级别来访问数据。
默认的隔离级别是read committed,也就是说比如,要访问一条数据,根据访问的性质,获取相应的锁。

如果有个进程A要读取数据,那么就会获取共享锁S,这个时候如果有另一个进程B,需要修改这条数据,那么他按照默认的隔离级别,就为了要修改这条数据,必须要申请一个独占锁X,于是他向sql server 申请x锁,sql server发现有一个进程获取了这条数据的S锁,正在读取数据,还有没读取完成,于是sql server 没有同意进程B的申请,于是B开始处于阻塞状态,他是被A进程阻塞的。

其实反过来也是一样的,如果A已经在修改数据,而B要读取数据,那么B会被A阻塞,这样就使得当有多个进程访问数据时,能实现数据的一致性,读的是一致性的数据,写的也是一致性的数据。

但是如果这个时候,用户修改了隔离级别为read uncommitted,那么进程就会读未提交的数据。
比如A进程修改了数据,还没有提交,B进程的隔离级别为read uncommitted,于是他可以不向sql server 申请共享锁,那么他就直接取内存中读取A已经修改的数据,而这个数据由于还没有提交,所以他读取到的数据是脏数据。

那么同样的,在另外2种隔离级别下,就能实现更加严格的隔离级别,也就是进程间的相互影响更小了。


2、数据库通过锁来实现数据的一致性。你说A读取完了数据,B就能修改了数据,等B修改了数据,A还是不能读取数据,只有等B修改且提交之后,A才能读取数据,这个时候A读取的就是一致的数据。

所谓一致的数据,是只状态,就是这个数据是处于一个确定的状态,而不是别人正在修改的数据,正改到一半呢,还没有全部改完,因为这个时候,如果别人发现,改错了,那么他就会回滚rollback。

这里讲另一个隔离级别,就是可重复读,很有意思。

比如现在有一个进程A,开启了一个事务,采用默认的read committed隔离级别,他在这个事务中有3个语句,第一个是读xx记录,第二个是修改yy记录,第三个还是读xx记录。

读第一个记录时值为1,接下来修改yy记录,修改完了再次读xx记录,发现值变成了2.

这是怎么回事呢?
其实在进程A修改yy记录时,有另一个进程B,去修改了xx记录,把只修改为2了。
由于是read committed隔离级别,在sql server中规定,在事务中读取数据时需要加共享锁S,但读取完成后,会立即释放共享S锁,于是B进程修改xx记录时,就顺利申请了X锁,修改完成后,提交了。
当A再次读取的时候,读取到了2,确实读取的也是已经提交的数据。

通过把隔离级别设置为可重复读,那么在一个事务中,要读取一条记录,所需要申请的共享锁S,要在事务提交或回滚的时候,也就是在事务结束的时候,才会被释放,这样就有效的阻止了进程B对xx记录的修改,那么对进程A来说,第一次和第二次读到的就都是1了。


3、死锁是一个普遍的问题,不是只有数据库才有死锁。
如果上过 *** 作系统的课,都会学过里面的死锁的概念,任何程序,只要是需要访问资源的,都有可能产生死锁。
死锁的产生,主要是和不当的编写程序有关。 一种死锁的情形是,简单来说就是,A进程有了资源1,A又想占有资源2,而B进程有了资源e,但还想用资源1,那么就形成了一个循环,就像三角恋一样,没结果,死循环了就是。 当然,在 *** 作系统和数据库中,都有死锁检测程序,比如在sql server 中就有一个“锁监视器”的线程,来检测死锁,如果一旦发现死锁,就会选择其中一个回滚代价较小的进程,进行回滚,这就解决了死锁问题。 在sql server内部有一个线程:Lock monitor,他的等待类型是:REQUEST_FOR_DEADLOCK_SEARCH,也就是死锁搜索请求,因为这个请求每个一段时间,会自动触发,就像一个定时任务一样。

总结

以上是内存溢出为你收集整理的MS SQLSERVER2008的事务、锁、并发的问题全部内容,希望文章能够帮你解决MS SQLSERVER2008的事务、锁、并发的问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1173133.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存