我今天在处理数据库的时候看到了锁这个概念,并对它感兴趣
数据库的锁定机制总结如下。乐观锁
乐观锁就像他的名字一样,认为别人(线程)去取数据时,别人不会修改数据,总是不会发生同时问题,所以不锁定,只在线程提交数据时检查版本号的形式数据表中通常会添加版本号[Version]字段,以指示修改的次数。 如果数据发生更改,则版本1仅在版本字段与当前数据库的版本值相同时才能成功提交
实现:基于大多数数据版本(Version )记录机制实现
特点:总是假设最好的情况
悲观锁
悲观锁定和乐观锁定是相反的存在。 他总是认为别人(另一个线程)会修改数据,所以他会锁上它。 (读锁定、写锁定等)一次只能允许一个线程修改数据,其他线程被阻止并锁定。 java中同步关键字的实现思想是悲观锁定。
实现:通常通过数据库锁定机制实现
特点:假设总是最坏的情况
乐观锁和悲观锁的用处
确保数据安全,处理高并发访问
乐观锁和悲观锁的区别
a. 加锁时机不同:
1 .悲观锁定,从数据开始修改时开始锁定数据,更改完成前不解锁
2 .乐观锁定,在数据修改完成并准备提交之前不锁定。 完成后请访问b.并发性区别
1 .由于悲观锁在事务执行过程中被锁定,因此并发量大可能会影响其他事务处理进程,导致其他事务处理进程的执行时间较长,事务处理超时
2 .乐观锁定在检查数据时进行锁定。 锁定时间会减少很多,但只有在锁定数据时才会影响其他事务。
3.2种锁各有优缺点,不能认为一方优于另一方。 与乐观锁定一样,如果应用于写入相对较少的情况,即在很少发生冲突的情况下,可以省略锁定开销,从而提高系统的整体吞吐量。 但是,如果冲突频繁发生,上级APP应用程序会不断进行retry,反而会降低性能,所以在这种情况下使用悲观的锁定比较合适
排它锁(写锁)
概念:
如果事务t对数据对象a施加写锁定,则事务t只允许读取和修改对象a,而其他事务对a施加任何类型的锁,只要事务t知道当前的写锁定将被释放
意义:
确保其他事务在事务t解除对数据对象a的锁定之前不能读取和修改数据对象a
共享锁(读锁)
概念:
如果事务t对数据对象a施加了读锁定,则其他事务可以对数据对象a施加读锁定,但不能对其施加写锁定。 我知道事务t解除了a的读锁定
意义:
虽然可以确保其他事务读取数据对象a,但在解除锁定之前不能更改a
相容矩阵
T1T2写锁定写锁定n写锁定读锁定n读锁定写锁定n读锁定读锁定Y 活锁
当事务a请求阻止数据对象r,事务b请求阻止r时,事务b等待事务a解除锁定,事务c也请求解除对r的锁定。 然而,在事务a解除对r的锁定之后,系统只能首先批准事务c的锁定r,然后事务b继续等待。 然后,在事务d也解除r的锁定之后,系统允许d对r进行锁定,并且事务b可以继续等待。 这种情况是永恒的
解决策略
可以用类似优先队列的方法解决。 如果多个事务被要求阻止统一数据对象,系统将按照请求的优先级对这些事务进行排队,并在解除对数据对象的锁定后首先批准队列中的第一个锁定
死锁
如果两个事务分别锁定两个单独的对象,则每个事务必须锁定另一个事务锁定的对象,因此每个事务将释放另一个事务当前占用的锁定
发生死锁时,系统会自动检测到它,并通过自动取消其中一个事务来终止死锁。 根据事务时间长度确定事务的优先级,处理时间较长的事务具有高优先级,发生冲突时保留高优先级事务,取消低优先级事务
解决策略
预防死锁必须破坏死锁的发生条件
1.一次封锁法:
单块方法要求一次锁定每个事务使用的所有数据。 如果不锁定,就无法继续执行
缺点:
1 .一次锁定所有数据,扩大了块范围,减少了系统并发量
2 .由于数据库中的数据始终在变化,因此很难预先确定需要为每个事务锁定的数据对象,只能扩大锁定范围,但同时性会降低
2.顺序封锁法
事先在数据中规定一个封锁顺序,按顺序封锁所有的东西
缺点:
1 .数据对象不确定,维护成本高