数据库锁
- 时间戳
在数据库表中单独加一列时间戳,比如“TimeStamp”,每次读出来的时候,把该字段也读出来,当写回去的时候,把该字段加1,提交之前 ,跟数据库的该字段比较一次,如果比数据库的值大的话,就允许保存,否则不允许保存
可以大大提高数据库处理的并发量,因为这种方法可以避免了长事务中的数据库加锁开销
- 分类
- 乐观锁
- 特点:
乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据;即不做任何控制,可认为不加锁。
- 使用CAS协议来处理:
从地址 V 读取值 A,执行多步计算来获得新 值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。
-
- 悲观锁
- 特点:
修改某条数据时,不允许别人读取该数据,只有等事务提交了,才释放锁,才允许其他用户访问那部分数据。
- 共享锁,读锁
简称S锁,所有的事务只能对其进行读操作不能写操作,加上共享锁后在事务结束之前其他事务只能再加共享锁,除此之外其他任何类型的锁都不能再加。
SELECT * from usertest where UserId='10011101' lock in share mode;
- 排它锁,独占锁,写锁
简称X锁,若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,在此事务结束之前,其他事务不能对其进行加任何锁,其他进程可以读取,不能进行写操作,需等待其释放。
update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型
SELECT * from usertest where UserId='10011101' for UPDATE;
- 其他分类
- 表锁
开销小,加锁快;并发读写容易出现表锁争夺而导致阻塞访问,但不会导致死锁
存在了表共享读锁和表独占写锁两种特点,即读读可并发,写写以及写读会阻塞
-
- 行锁
开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。InnoDB独有的
InnoDB行锁是通过索引上的索引项来实现的,而Oracle是通过在数据中对相应数据行加锁来实现的
- 导致的问题
- 活锁
- 特点:
是T1封锁了数据R,T2同时也请求封锁数据R,T3也请求封锁数据R,当T1释放了锁之后,T3会锁住R,T4也请求封锁R,则T2就会一直等待下去;这种处理方法就是采用“先来先服务”策略。
-
- 死锁
- 特点:
我等你,你又等我,比如:T1封锁了数据R1,正请求对R2封锁,而T2封住了R2,正请求封锁R1。
- 预防方法
一次性把所需要的数据全部封锁住,或者只能按照规定的顺序来封锁
- 死锁判断
等待时间超过指定时限,或者事务等待图中出现了回路