1、数据库锁表的意思:因为在数据库里,同一个数据可能有多个人来读取或更改,为了防止我更改的时候别人也同时更改,这是一般要锁住表不让别人改。
2、举个简单例子:在更新数据库记录的过程中,我是不希望别人也来更新我的这些记录的,像库存,做出库的时候,原数量100,我出了20,我就需要把数量更新到80;
在更新的过程中,别人又做了30的出库,如果在我更新的时候,别人先把库存更新到70,然后我又更新80,那数量就错误了。所以我更新的时候,我就需要锁定这条记录。这是数据行锁,排他锁。
扩展资料:
数据库锁表的必要条件:
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
行锁的等待
在介绍如何解决行锁等待问题前,先简单介绍下这类问题产生的原因。产生原因简述:当多个事务同时去 *** 作(增删改)某一行数据的时候,MySQL 为了维护 ACID 特性,就会用锁的形式来防止多个事务同时 *** 作某一行数据,避免数据不一致。只有分配到行锁的事务才有权力 *** 作该数据行,直到该事务结束,才释放行锁,而其他没有分配到行锁的事务就会产生行锁等待。如果等待时间超过了配置值(也就是 innodb_lock_wait_timeout 参数的值,个人习惯配置成 5s,MySQL 官方默认为 50s),则会抛出行锁等待超时错误。
如上图所示,事务 A 与事务 B 同时会去 Insert 一条主键值为 1 的数据,由于事务 A 首先获取了主键值为 1 的行锁,导致事务 B 因无法获取行锁而产生等待,等到事务 A 提交后,事务 B 才获取该行锁,完成提交。这里强调的是行锁的概念,虽然事务 B 重复插入了主键,但是在获取行锁之前,事务一直是处于行锁等待的状态,只有获取行锁后,才会报主键冲突的错误。当然这种 Insert 行锁冲突的问题比较少见,只有在大量并发插入场景下才会出现,项目上真正常见的是 update&delete 之间行锁等待,这里只是用于示例,原理都是相同的。
三、产生的原因根据我之前接触到的此类问题,大致可以分为以下几种原因
你理解错了!默认sqlserver都是行数据锁定,隔离级别是 read commited 也就是读取可 提交数据。
我给你举个例子!
SELECT TOP 1000
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo][DeleteLog]
显示结果
-----------------------------------------------
ID DeleteBy DelDate
1 admin 2008-04-13 00:00:00000
2 admin 2008-05-04 00:00:00000
-------------------------------------------------
表数据就两行
然后我做如下 *** 作:
打开 SQL Server Management Studio
输入:
begin transaction
DELETE FROM [HMS][dbo][DeleteLog]
where ID='1'
在另一个窗口中:
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo][DeleteLog]
where ID=1
你发现 这一个窗口被阻塞了,
但是查询
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo][DeleteLog]
where ID=2
可以正确返回结果。 这充分证明了,sqlserver默认隔离级别是行数据锁定。
然后你此时在第一个删除窗口 中输入
rollback
,记住前面的删除不执行,只执行rollback。
此时看一下查询
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo][DeleteLog]
where ID=1
那个窗口的结果已经出来了,阻塞被解除了。
========================================
当然了!你执行了全表检索肯定也是被阻塞的,因为删除 *** 作还没提交啊,检索数据中又包含了你要删除的数据,当然被阻塞了。
你的问题出现在哪里了,你应该明白了吧!
解决这个问题其实很简单,不要长事务占用。检索的时候避开要删除的数据。
当然也可以改变隔离级别,sqlserver分为两类隔离级别,改成非阻塞类就可以。
但是我个人不推荐这么做。改变隔离级别可以如下方式:
set transaction isolation level read uncommitted
begin transaction
DELETE FROM [HMS][dbo][DeleteLog]
where ID='1'
这个删除没有提交
检索的时候
set transaction isolation level read uncommitted
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo][DeleteLog]
where ID=1
根本不会阻塞。 比较顺利,删除更新也一样。
这种方式 适合 数据量庞大的社交,天文数据库,企业管理不适合。
可以从侧面看出,你的程序并不优良,明白了否?
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)