什么是数据库的锁,举例说明一下
数据库的锁用来锁住数据库中的某些数据,使得当前只能有一个用户/会话可以更新数据。所以,数据库的锁用来防止同时有一个或多个用户更新同一块数据。当数据被锁起来,这意味着另一个数据库会话在锁释放之前不能更新这块被锁起来的数据。
画重点:
- 锁住数据库中的某些数据,使得当前只能有一个用户/会话可以更新数据
- 用来防止同时有一个或多个用户更新同一块数据
- 另一个数据库会话在锁释放之前不能更新这块被锁起来的数据
当另一个会话尝试更新某块被锁起来的数据,会怎样处理
假如会话A
尝试访问被会话B
锁起来的数据,会话A会发生什么?会话A会被置于lock wait
状态,并且会话A接下来不会进行任何事务操作。也就是说,A会被“暂停”,直到B把锁释放掉。
如果一个会话为了等待锁释放,对于有些数据库例如DB2,会设置一个超时时间,当超过这个时间还没有等到锁被释放掉,就会停止等待,并抛出错误。但Oracle会一直无限等下去。所以不同的数据库处理lock wait
状态的机制是不一样的。
锁的粒度
数据库的锁有不同的层级,既锁的粒度(lock granularity)。下面是几种常见的粒度:
- Database level locking
-
File level locking
-
Table Level Locking
-
Page or Block Locking
-
Column Level Locking
-
Row Level Locking
数据库层级的锁
这种锁会将整个数据库都锁住,意味着当前只能有一个会话可以对数据库进行更新操作。这种锁不经常使用,因为阻止了其他所有用户,只留下一个可以对数据库进行操作。但这各种锁在数据库更新的时候很有用,例如将数据库更新到新版本。Oracle有一个exclusive mode
,就是这种层级的锁。
文件层级的锁
这种层级锁会把整个数据库文件锁住。但问题来了,什么是数据库文件呢(a file in a datebase
)?数据库文件里面保存的是某些数据——可以是整张表的数据,也可以是表的一部分数据,甚至是几张表的部分数据。因为许多数据混在一起存到一个文件里,所以这种文件层级的锁不怎么使用。
表层级的锁(table level locking)
这种锁很好理解——整张表都被锁住。当对整张表进行操作(例如更新表中的所有行,修改或删除某些列),这种锁就非常实用。在Oracle中,这种锁叫DDL锁
,DDL——Data Definition Language
, 包含了create drop alter
等操作,会对整张表进行修改。
块层级的锁
数据库文件的某一块被锁住,这种锁也不常用。因为数据可以存储到不连续的多个块上。
列级的锁(column level locking)
这种锁也不常用,因为要花费大量的资源来实现它。
行级锁(row level locking)
这种锁锁住表中的一行数据。这是最常用的一种锁,几乎所有的数据库都支持行级锁
数据库会自动启用锁机制吗?
即使你没有在SQL语句中写特定的语句来使用锁,当进行update或delete操作时,锁都会被启用。
例如我们有如下语句:
数据库首先找到some_columns
值为XYZ
的所有行,将这些行都锁住,以防止其他会话同时进行更新操作。
当加了锁时,可以读数据吗?
看加的是什么锁了,有的锁是read-exclusive
, 有这种锁的时候,其他会话读数据都不行。
什么是锁的竞态(lock contention)
使用锁的一个问题是会产生竞争,因为数据被加了锁,其他多个会话会同时申请对数据的更新操作。如果情况不严重,某些用户操作会卡顿,因为需要等待锁的释放。严重情况下,多个会话都在等待锁释放,有些会话会陷入无限等待状态。当会话陷入无限等待状态,这种情况就被称之为死锁
。
翻译自:https://www.programmerinterview.com/index.php/database-sql/database-locking/
https://kongpingfan.me/2018/09/05/database-locking/