我们在上面的DistributedLock类中创建一个lock方法 。
当线程执行完任务后,必须手动的执行解锁操作,之前被锁住的线程才能继续干活 。在我们上面的实现中,其实就是获取到当时select for update 成功的线程对应的Connection,并实行commit操作即可 。
那么如何获取到呢?我们可以利用ThreadLocal 。首先在DistributedLock类中定义
每次调用lock方法的时候,把Connection放置到ThreadLocal里面 。我们修改lock方法 。
这样子,当获取到Connection后,将其设置到ThreadLocal中,如果lock方法出现异常,则将其从ThreadLocal中移除掉 。
有了这几步后 , 我们可以来实现解锁操作了 。我们在DistributedLock添加一个unlock方法 。
毕竟是利用DB来实现分布式锁 , 对DB还是造成一定的压力 。当时考虑使用DB做分布式的一个重要原因是,我们的应用是后端应用,平时流量不大的,反而关键的是要保证库存数据的正确性 。对于像前端库存系统 , 比如添加购物车占用库存等操作,最好别使用DB来实现分布式锁了 。
如果想锁住多份数据该怎么实现?比如说,某个库存操作,既要修改物理库存,又要修改虚拟库存,想锁住物理库存的同时,又锁住虚拟库存 。其实也不是很难,参考lock方法,写一个multiLock方法,提供多个transactionId的入参 , for循环处理就可以了 。这个后续有时间再补上 。
mysql 的锁以及间隙锁mysql 为并发事务同时对一条记录进行读写时,提出mysql锁怎么实现的了两种解决方案:
1)使用 mvcc mysql锁怎么实现的的方法,实现多事务mysql锁怎么实现的的并发读写,但是这种读只是“快照读”,一般读mysql锁怎么实现的的是历史版本数据,还有一种是“当前读”,一般加锁实现“当前读”,或者 insert、update、delete 也是当前读 。
2)使用加锁的方法,锁分为共享锁(读锁),排他锁(写锁)
快照读:就是select
当前读:特殊的读操作 , 插入/更新/删除操作,属于当前读,处理的都是当前的数据,需要加锁 。
mysql 在 RR 级别怎么处理幻读的呢?一般来说,RR 级别通过 mvcc 机制,保证读到低于后面事务的数据 。但是 select for update 不会触发 mvcc,它是当前读 。如果后面事务插入数据并提交,那么在 RR 级别就会读到插入的数据 。所以,mysql 使用 行锁 + gap 锁(简称 next-key 锁)来防止当前读的时候插入 。
Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生 。
Innodb自动使用间隙锁的条件:
轻松掌握MySQL数据库锁机制的相关原理[1] 在一个update和insert操作频繁的表中 少量数据测试的时候运行良好 在实际运营中 因数据量比较大( 万条记录) 会出现死锁现象 用show processlist查看 可以看到一个update语句状态是Locked 一个delete语句状态是Sending data 查看了一下参考手册 把锁定相关的资料整理下来 以便自己记录和追踪该问题的解决情况
MySQL 支持对MyISAM和MEMORY表进行表级锁定 对BDB表进行页级锁定 对InnoDB 表进行行级锁定 在许多情况下 可以根据培训猜测应用程序使用哪类锁定类型最好 但一般很难说出某个给出的锁类型就比另一个好 一切取决于应用程序 应用程序的不同部分可能需要不同的锁类型 为了确定是否想要使用行级锁定的存储引擎 应看看应用程序做什么并且混合使用什么样的选择和更新语句 例如 大多数Web应用程序执行许多选择 而很少进行删除 只对关键字的值进行更新 并且只插入少量具体的表 基本MySQL MyISAM设置已经调节得很好
在MySQL中对于使用表级锁定的存储引擎 表锁定时不会死锁的 这通过总是在一个查询开始时立即请求所有必要的锁定并且总是以同样的顺序锁定表来管理
推荐阅读
- jquery判断控制,jquery判断控件是否存在
- redis客户端下怎么退格,redis怎么退出
- js如何拖动合并单元格,js 拖动
- 江西vps虚拟主机,虚拟主机平台
- go语言分割字符串 go字符串处理
- vue或者jquery,vuejs jqueryjs
- 美食拍摄包括什么,美食拍摄有哪些要点
- 如何在小区推广产品销售,如何在小区推广产品销售话术
- vb.net注册回调 vb控件注册