You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Advantage本地服务器(ALS)中用SQL锁定记录避免并发更新?

针对Advantage本地服务器(ALS)的记录冲突解决建议

方案1:利用ALS的悲观记录锁定机制

ALS原生支持悲观记录级锁定,你可以通过Delphi的TAdsTable组件(而非TQuery)实现,步骤如下:

  • 将组件的LockType属性设置为ltPessimistic(悲观锁模式)
  • 打开表后,通过唯一ID定位目标记录
  • 调用Edit方法触发锁定,此时其他用户无法修改该记录,直到你执行Post提交或Cancel取消编辑

示例Delphi代码:

var
  AdsTable: TAdsTable;
begin
  AdsTable := TAdsTable.Create(nil);
  try
    AdsTable.Connection := YourALSConnection;
    AdsTable.TableName := 'target_table';
    AdsTable.LockType := ltPessimistic;
    AdsTable.Open;
    
    // 通过唯一ID定位待更新记录
    if AdsTable.Locate('unique_id', TargetRecordID, []) then
    begin
      AdsTable.Edit; // 锁定当前记录
      AdsTable.FieldByName('number').AsInteger := UpdatedValue;
      AdsTable.Post; // 提交后自动释放锁
    end;
  finally
    AdsTable.Free;
  end;
end;

方案2:乐观锁实现(低冲突场景首选)

如果不想因悲观锁导致记录长时间锁定,可采用乐观锁逻辑,核心是更新时验证记录是否被篡改:

  1. 给数据表新增一个版本字段(如version,整数类型,每次更新自增)或时间戳字段(last_modified)
  2. 查询记录时同时获取版本号/时间戳
  3. 更新时携带该值,仅当数据库中对应记录的版本号/时间戳与查询值一致时,才执行更新操作

示例SQL逻辑(基于版本号):

-- 查询记录及版本号
SELECT number, version FROM target_table WHERE unique_id = :TargetID;

-- 带验证的更新语句
UPDATE target_table 
SET number = :NewValue, version = version + 1 
WHERE unique_id = :TargetID AND version = :OriginalVersion;

执行更新后检查受影响行数:若返回0,说明记录已被其他用户修改,需提示用户重新获取最新数据后再操作。

方案3:表级独占锁(极端场景使用)

若需确保整个操作周期内记录完全不被访问,可给表加独占锁,但注意这会阻塞其他用户对该表的所有操作,仅适合极短时间的操作:

AdsTable.Exclusive := True;
AdsTable.Open;
// 执行更新操作
AdsTable.Close; // 关闭表后释放独占锁

关于你之前代码的说明

你之前的SELECT number FROM table WHERE 1=1语句不会锁定任何记录,ALS默认查询为快照读取模式,不会对记录施加锁,因此无法起到冲突预防作用。

内容的提问来源于stack exchange,提问作者Leo Bidi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 07:39:52