Sql “如何阅读全部”;上次“更改”;火鸟数据库的记录?
我的问题有点棘手,因为它主要是一个逻辑问题。Sql “如何阅读全部”;上次“更改”;火鸟数据库的记录?,sql,triggers,firebird,Sql,Triggers,Firebird,我的问题有点棘手,因为它主要是一个逻辑问题。 我试图通过将所有内容读取到内存中来优化我的应用程序速度,但只读取那些记录,这些记录自“上次读取”=上次加载记录的最大时间戳后发生了变化 FirebirdSQL数据库引擎不允许直接更新“After Trigger”中的字段,因此它显然使用“before update or insert”触发器更新字段new.last\u changed=current\u timestamp 问题是: 事实证明,这是一种完全错误的方法,因为这些触发器在事务启动时触发
我试图通过将所有内容读取到内存中来优化我的应用程序速度,但只读取那些记录,这些记录自“上次读取”=上次加载记录的最大时间戳后发生了变化 FirebirdSQL数据库引擎不允许直接更新“After Trigger”中的字段,因此它显然使用“before update or insert”触发器更新字段
new.last\u changed=current\u timestamp代码>
问题是:
事实证明,这是一种完全错误的方法,因为这些触发器在事务启动时触发
因此,如果有一个事务比另一个事务花费更多的时间,则保存的“上次更改的时间”将低于触发并在其间完成的短突发事务。
1。tr:13:00:01.400提交。。。每次修改时。
这样我:
- 不必用日志数据填充数据库
- 我可以使用
WHERE last_sequence>1直接查询表代码>李>
- 无需先预查询“记录器表”
我只是担心:如果事务提交时的触发器试图更新最后一个序列
字段,而在触发器锁定(另一个表的)记录之前,第2个事务处于打开状态,会发生什么情况?
这会发生吗 最终解决方案基于以下理念:
插入或更新前每个表的触发器可以推送事务的时间:RDB$SET_上下文('USER_transaction','table31',current_timestamp
)李>
如果接收到这样的上下文,事务提交时的全局触发器可以将序列+时间插入“日志记录表”李>
它甚至可以通过只记录“大时差”(如>=1分钟)来处理“夏时制更改”和“间隔”,以减少记录量。)
存储过程可以简化并加快每个查询的“上次查询时间”的计算李>
例子:
1.)
(二、三)
在事务提交位置1上激活提交后创建触发器TRG\u SYNC\u
声明变量N时间戳;
声明变量T VARCHAR(255);
开始
N=转换(“现在”作为时间戳);
T=RDB$GET_上下文('USER_TRANSACTION'、'orders_table');
如果(:T不为空),则开始
如果(:N<:T),则T=:N--系统时间已更改,例如:夏令时“-1小时
如果(datediff(从:T到:N的秒数)>60),则--超过1分钟
插入“同步过去的时间”(ID、表号、训练开始、同步时间、C用户)
值(GEN_ID(GEN_SYNC_pass_TIMES,1),31,强制转换(:T作为时间戳),:N,当前_用户);
结束;
T=RDB$GET_CONTEXT('USER_TRANSACTION','details_table');
--其他表格。。。
当有人退出时;
结束
最终解决方案基于以下理念:
插入或更新前每个表的触发器可以推送事务的时间:RDB$SET_上下文('USER_transaction','table31',current_timestamp
)
如果接收到这样的上下文,事务提交时的全局触发器可以将序列+时间插入“日志记录表”
它甚至可以通过只记录“大时差”(如>=1分钟)来处理“夏时制更改”和“间隔”,以减少记录量。)
存储过程可以简化并加快每个查询的“上次查询时间”的计算
例子:
1.)
(二、三)
在事务提交位置1上激活提交后创建触发器TRG\u SYNC\u
声明变量N时间戳;
声明变量T VARCHAR(255);
开始
N=转换(“现在”作为时间戳);
T=RDB$GET_上下文('USER_TRANSACTION'、'orders_table');
如果(:T不为空),则开始
如果(:N<:T),则T=:N;--系统时间已更改,例如:夏令时“-1小时
如果(datediff(从:T到:N的秒数)>60),则——超过1分钟。通过
插入“同步过去的时间”(ID、表号、训练开始、同步时间、C用户)
值(GEN_ID(GEN_SYNC_pass_TIMES,1),31,强制转换(:T作为时间戳),:N,当前_用户);
结束;
T=RDB$GET_CONTEXT('USER_TRANSACTION','details_table');
--其他表格。。。
当有人退出时;
结束
我想我看到了问题,但你的叙述对我来说有点不清楚。@pilcrow“Edit1”补充道:“你能给我们展示一个非常简单的表,其中包含一些行、你尝试过的触发器以及你想要发生的事情吗?”。用其他词语解释目标。添加了一些代码示例。IMHO由于此问题影响所有行的所有类型的表,因此此问题的示例无法解释任何内容。您可以尝试在提交时使用ON COMMIT
trigger。RAWT方案是每个表触发器记录哪些记录在提交时被更新、插入或删除到某个clear-on-commitGTT
或某个持久表中,并在其中标记有事务ID(current_Transaction
)。然后,提交时的触发器将按时间戳重新标记这些记录(包括已删除的记录)。也许您最好放弃2层模型,切换到3层模型。数据库->应用服务器->多个客户端。然后,它应该是保持状态,哪个客户拥有哪个数据公文包,以及如何将最后一刻的更改复制到这些客户。我想我看到了问题所在,但你的叙述对我来说有点不清楚。@pilcrow“Edit1”补充道:“你能给我们展示一个非常简单的表,其中包含一些行、你尝试过的触发器以及你想要发生的事情吗?”。用其他词语解释目标。添加了一些代码示例。IMHO由于此问题影响所有行的所有类型的表,因此此问题的示例无法解释任何内容。您可以尝试在提交时使用ON COMMIT
trigger。RAWT方案是按表触发器记录哪些记录被更新、插入或删除到某个clear-on-commitGTT
或
alter trigger SYNC_ORDERS active after insert or update position 999 AS
declare variable N timestamp;
begin
N = cast('NOW' as timestamp);
if (new.last_changed <> :N) then
update ORDERS set last_changed= :N where ID=new.ID;
end
Query1.SQL.Text := 'SELECT * FROM orders WHERE last_changed >= ' + DateTimeToStr( latest_record );
Query1.Open;
latest_record := Query1.FieldByName('last_changed').asDateTime;
ID TableID Changed
===========================
1 5 2019.11.27 19:36:21
2 5 2019.11.27 19:31:19
create trigger ORDERS_BI active before insert or update position 0 AS
BEGIN
IF (NEW.ID IS NULL) THEN
NEW.ID = GEN_ID(GEN_ORDERS,1);
RDB$SET_CONTEXT('USER_TRANSACTION', 'orders_table', current_timestamp);
END
create trigger TRG_SYNC_AFTER_COMMIT ACTIVE ON transaction commit POSITION 1 as
declare variable N TIMESTAMP;
declare variable T VARCHAR(255);
begin
N = cast('NOW' as timestamp);
T = RDB$GET_CONTEXT('USER_TRANSACTION', 'orders_table');
if (:T is not null) then begin
if (:N < :T) then T = :N; --system time changed eg.: daylight saving" -1 hour
if (datediff(second from :T to :N) > 60 ) then --more than 1min. passed
insert into "SYNC_PAST_TIMES" (ID, TABLE_NUMBER, TRG_START, SYNC_TIME, C_USER)
values (GEN_ID(GEN_SYNC_PAST_TIMES, 1), 31, cast(:T as timestamp), :N, CURRENT_USER);
end;
T = RDB$GET_CONTEXT('USER_TRANSACTION', 'details_table');
-- other tables ...
when any do EXIT;
end