数据库中的锁
乐观锁
1.什么是乐观锁/谈一下你对乐观锁的理解
乐观锁实际上并没有加锁,只是一种思想,就是我们总是认为当其他线程获取数据的时候不会修改数据,只有在线程提交数据时会通过检查版本号的形式检测数据有没有被修改过
mysql中没有乐观锁,只有悲观锁
2.乐观锁实现的方式有哪些,具体怎么实现
版本号机制:
在数据表(如:user表)添加version字段表示被修改的次数,当数据被修改,version的值加1,只有当数据库表version值与查询出来的version值相同时才会提交成功
update user set name=#{name} , version=#{newVersion} where id=#{id} and version=#{oldVersion}
其中newVersion=oldVersion+1
若该语句返回1,则表示更新成功;若返回0,则表示前后的version不一致,产生冲突,更新失败
如果同时修改id=1的name和sex,分为2个不同sql语句同时执行,后执行的语句会因为先执行的更新了version值导致其更新失败
解决方案:为每个需要乐观锁的字段单独设置版本号字段
CAS算法(compare And Swap比较和互换算法):
CAS算法涉及到3个操作数
1、需要读写的内存值V
2、进行比较的值A
3、拟写入的新值B
当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。
3.乐观锁使用场景有哪些
适合读取操作比较频繁的场景。如:场景:定时job如何做并发控制,保证只有一台服务器执行?
首先每条job都会配置在数据库中,初始状态是N,如果有job开始跑了,会先把状态置为Y
-
update
-
job_table jt
-
set
-
jt.status = 'Y',
-
jt.update_date = sysdate
-
where
-
jt.job_code = 'job_a_code' and
-
jt.status = 'N'
期望值N可以理解为CAS中的内存值
Y就是CAS中的拟写入的新值B
参数N就是CAS中的进行比较值
悲观锁
1.什么是悲观锁
悲观锁也是一种思想,就是我们总认为其他线程获取数据的时候会修改数据,所以都会加锁,一次只能允许一个线程对数据进行修改,其他线程会被阻塞挂起,java中的synchronized关键字的实现思想就是悲观锁
悲观锁分为行级锁、页级锁和表级锁
行级锁分为排它锁(读锁)、共享锁(写锁)、更新锁和意向锁
表级锁分为排它锁、共享锁、意向锁
数据库sql怎么加锁?
在sql语句后面加上for update
如:
start TRANSACTION;
explain select * from test where name = 1 for update
select * from test where name = 1 for update
COMMIT;
排它锁(写锁):如果事务T对数据对象A加上写锁,那么只允许事务T读取和修改对象A,其他事务都不能在对A加任何类型的锁,直到事务T释放当前写锁
共享锁(读锁):如果事务T对数据对象A加上读锁,那么其他事务只能再对数据对象A加读锁,而不能加写锁,直到事务T释放在A上的读锁
2.悲观锁使用场景
适用于写入操作比较频繁的操作
3.如何查看mysql数据库中是否有使用锁
SHOW STATUS LIKE 'Table_locks%';
Table_locks_immediate表示表被锁了总数
Table_locks_waited表示有多少请求等待表锁