行锁的实现

1
2
3
4
5
6
7
8
// 先查询设备并加锁
PmlDevice device = pmlDeviceMapper.selectByIdForUpdate(pmlDeviceDto.getDeviceNo());
if (device == null) {
// 处理设备不存在的情况
return AjaxResult.error("第"+a+"行设备不存在,请确认后重新导入!");
}
// 更新设备信息
device.setDealerUserId(pmlDeviceDto.getDealerUserId());
1
2
3
<select id="selectByIdForUpdate" resultType="com.pml.domain.PmlDevice">
SELECT * FROM pml_device WHERE device_no = #{deviceNo} FOR UPDATE
</select>

添加时机:在select … for update 语句时给查询到的记录添加一个排他锁(也称为行锁或写锁),以防止其他事务对同一行数据进行修改

释放时机:行锁通常在当前事务结束时自动释放。事务可以通过以下几种方式结束:
提交事务:如果事务成功完成所有操作并且调用了提交方法(例如 transactionManager.commit()),行锁会被释放。
回滚事务:如果事务过程中发生了错误并且调用了回滚方法(例如 transactionManager.rollback()),行锁也会被释放。

在Java中,如果你使用的是Spring框架,事务管理通常是通过注解(如 @Transactional)来实现的。在这种情况下,事务的边界由方法的开始和结束决定。因此,行锁会在方法返回时(无论是正常返回还是抛出异常)被释放。


表锁的实现

1
2
3
4
5
6
7
BEGIN;
LOCK TABLES devices WRITE;
-- 执行更新操作
UPDATE devices SET dealer_user_id = 'new_user_id' WHERE device_no = 'device_no';
-- 释放表锁
UNLOCK TABLES;
COMMIT;

表锁会显著降低并发性能,因为它们会阻止其他事务对表的访问

不当使用表锁可能导致死锁,特别是在复杂的事务环境中

确保在事务中正确地添加和释放表锁,以避免锁泄漏

如果你需要在应用程序中实现表锁,建议根据具体的数据库系统选择合适的语法和方法。同时,尽量减少表锁的使用,转而使用更细粒度的行锁来提高并发性能。