基于MySql的InnoDB引擎,只有通过索引进行检索的时候才会使用行级锁,否则会使用表级锁.这个索引一定要创建成唯一索引,否则会出现多个重载方法之间无法同时被访问的问题
每个事务锁在表中为一条数据。
服务启动,查询t_lock表。准备获取锁。
select * from t_lock;若表中无数据(服务初次启动),则进行添加:
INSERT INTO `t_lock`(`id`, `relock`, `method`, `ip`, `lock_time`) VALUES (1, 1, 'test', '127.0.0.1', NOW());若添加成功,则认为获取到锁。
若表中有数据,则relock是否为 0。 1) 若锁定次数为0, 则可以自由获取锁。获取锁执行sql获取锁。
UPDATE `t_lock` SET `relock` = 1, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 0; 若锁定次数不为0, 则判断ip和method是否一致。若一致,则可以进行重入。执行sql重入锁。 UPDATE `t_lock` SET `relock` = 2, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 1; --假定表中锁定次数为 1 若不一致,则轮询获取锁。获取锁规则为:1. 锁超时 2. 其他人释放锁。 锁超时: 锁定时间和当前时间的比较。若时间偏差过大(业务系统自己配置),则可以强制获取锁。
其他人释放锁: relock = 0
UPDATE `t_lock` SET `relock` = 1, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method = 'test' AND ( ( relock = 2 AND NOW() > DATE_ADD( '2001-09-11 07:35:25', INTERVAL 5 MINUTE )) OR relock = 0 ); --假定表中锁定次数为 2, 超时时间5分钟 考虑到各个服务器时间可能和数据库时间不一致。 所以使用数据库时间。传入时间为首次查询得到的数据库时间。
以上update操作,若成功,则获取到相应锁。
锁释放。
UPDATE `t_lock` SET `relock` = 0, `method` = 'test', `ip` = '127.0.0.1', `lock_time` = NOW() WHERE `ip` = '127.0.0.1' AND method='test' AND relock = 1; --假定表中锁定次数为 1若被重入,则需多次释放。
注: 此设计 无法体现公平。支持多种数据源(jdbc, redis,zk,mongodb …),详情参照: https://blog.csdn.net/qq_36341209/article/details/87375794