使用数据库行存储有关行的元数据?
关于存储一行元数据的最佳实践是什么?
以银行间金融转账为例。 Transfer
可能看起来像:
CREATE TABLE Transfers (
TransferID int,
FromTransit varchar(10),
FromBranch varchar(10),
FromAccount varchar(50),
ToTransit varchar(10),
ToBranch varchar(10),
ToAccount varchar(50),
Amount money,
Status varchar(50));
但是现在,人们当然希望看到元数据:
ALTER TABLE Transfers
ADD
CreatedDate datetime,
LastModifiedDate datetime,
CreatedByUsername varchar(50),
CreatedByFullname varchar(200),
CreatedByWorkstation varchar(50),
VoidedDate datetime NULL,
VoidedByUsername datetime NULL,
VoidedByFullname datetime NULL,
VoidApprovedBySupervisorUsername varchar(50) NULL,
VoidApprovedBySupervisorFullname varchar(200) NULL,
VoidApprovedBySupervisorWorkstation varchar(50) NULL,
SentDate datetime NULL,
SentByUsername varchar(50) NULL,
SentByFullname varchar(50) NULL,
SentByWorkstation varchar(50) NULL,
SendApprovedBySupervisorUsername varchar(50) NULL,
SendApprovedBySupervisorFullname varchar(50) NULL,
SendApprovedBySupervisorWorkstation varchar(50) NULL,
SendConfirmationNumber varchar(50) NULL,
SentToRemoteMachineName varchar(50) NULL,
ReceivedDate datetime NULL,
ReceivedConfirmationNumber varchar(50) NULL,
ReceivedToRemoteMachineName varchar(50) NULL,
ReceivedByUsername varchar(50) NULL,
ReceivedByFullname varchar(50) NULL,
ReceivedByWorkstation varchar(50) NULL,
ReceiveApprovedBySupervisorUsername varchar(50) NULL,
ReceiveApprovedBySupervisorFullname varchar(50) NULL,
ReceivedApprovedBySupervisorWorkstation varchar(50) NULL,
ReceivedCheckedBySupervisorUsername varchar(50) NULL,
ReceivedCheckedBySupervisorFullname varchar(50) NULL,
ReceivedCheckedBySupervisorWorkstation varchar(50) NULL
)
这些都是定义明确的值,它们都将出现在与传输相关的硬拷贝上。
我们已经对表中的更改进行了审核日志记录,但这不会捕获类似以下内容:
UPDATE Transfers SET Status = 'TransferStatus_Received'
WHERE TransferID = 6744891
它会捕获用户名、全名和机器名称 > 做出改变的人;但它无法知道负责输入凭据以“授权”接收转账的主管的姓名。
当他们要求跟踪另一条信息时,我的烦恼就来了,我必须向我的数据表中添加更多的元数据列。
这是最佳实践吗?
What are the best practices regarding storing metadata about a row with a row?
Take the example of a inter-bank financial transfer. The Transfer
might look like:
CREATE TABLE Transfers (
TransferID int,
FromTransit varchar(10),
FromBranch varchar(10),
FromAccount varchar(50),
ToTransit varchar(10),
ToBranch varchar(10),
ToAccount varchar(50),
Amount money,
Status varchar(50));
But now, of course, people will want to see meta-data:
ALTER TABLE Transfers
ADD
CreatedDate datetime,
LastModifiedDate datetime,
CreatedByUsername varchar(50),
CreatedByFullname varchar(200),
CreatedByWorkstation varchar(50),
VoidedDate datetime NULL,
VoidedByUsername datetime NULL,
VoidedByFullname datetime NULL,
VoidApprovedBySupervisorUsername varchar(50) NULL,
VoidApprovedBySupervisorFullname varchar(200) NULL,
VoidApprovedBySupervisorWorkstation varchar(50) NULL,
SentDate datetime NULL,
SentByUsername varchar(50) NULL,
SentByFullname varchar(50) NULL,
SentByWorkstation varchar(50) NULL,
SendApprovedBySupervisorUsername varchar(50) NULL,
SendApprovedBySupervisorFullname varchar(50) NULL,
SendApprovedBySupervisorWorkstation varchar(50) NULL,
SendConfirmationNumber varchar(50) NULL,
SentToRemoteMachineName varchar(50) NULL,
ReceivedDate datetime NULL,
ReceivedConfirmationNumber varchar(50) NULL,
ReceivedToRemoteMachineName varchar(50) NULL,
ReceivedByUsername varchar(50) NULL,
ReceivedByFullname varchar(50) NULL,
ReceivedByWorkstation varchar(50) NULL,
ReceiveApprovedBySupervisorUsername varchar(50) NULL,
ReceiveApprovedBySupervisorFullname varchar(50) NULL,
ReceivedApprovedBySupervisorWorkstation varchar(50) NULL,
ReceivedCheckedBySupervisorUsername varchar(50) NULL,
ReceivedCheckedBySupervisorFullname varchar(50) NULL,
ReceivedCheckedBySupervisorWorkstation varchar(50) NULL
)
These are all well-defined values, that will all appear on the hard-copy related to a transfer.
We already have audit logging of changes in tables, but that wouldn't catch something like:
UPDATE Transfers SET Status = 'TransferStatus_Received'
WHERE TransferID = 6744891
It would catch the username, fullname, and machine name of the person who made the change; but it can't know the name of the supervisor who was over the person's shoulder to enter their credentials to "authorize" the transfer to be received.
My aggravation comes when they ask for another piece of information to be tracked, and I have to add more metadata columns to my data table.
Is this best practice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于金融数据库来说,这不是一个好的做法,因为您允许更新。如果您允许更新,那么您添加什么日志记录、审计、加密密钥或任何内容都无关紧要,因为敌对方可以直接更新它们。
相反,您必须禁止更新;所有更改都必须是插入。所有表都应该有一个带索引的顺序 FK 列,并且所有连接都在
Max(seq)
上。这意味着您对最新数据执行所有事务,但在这些表上拥有每个事务的永久记录。编辑:如果您询问的是是否应该将审核列添加到原始表中,这取决于审核列是否稀疏或可为空。从你的评论来看,似乎是这样。
在这种情况下,您应该为每个可为空的审核属性组创建单独的表,并对这些表执行外连接,与原始数据库的顺序列连接。这意味着您可以随意添加或删除审计表,而不会影响您的数据表。例如:
如果您需要在事务中重用它,您可以创建一个视图或存储过程来保存 Max(seq) 。
This is not good practice for financial databases because you allow updates. If you allow updates it does not matter what logging, auditing, crypto keys or whatever you add since a hostile party could just update them.
Instead you must forbid updates; all changes must be inserts. All tables should have an indexed sequential FK column and all joins are on
Max(seq)
. This means you perform all transactions on the latest data but have a permanent record of every transaction on these tables.Edit: If what you're asking is whether you should add the audit columns to the original table, that depends if the audit columns are sparse or nullable. From your comments, it seems they are.
In that case, you should create separate tables for each nullable group of audit attributes and perform an outer join on those tables, joining with the sequential column of the original database. This means you can add or drop audit tables at will without affecting your data table. Something like:
You can create a view or stored procedure that saves
Max(seq)
if you need to reuse it in a transaction.我对 SQL Server 不太了解,但是当在 Oracle 场景中遇到这种情况时,我倾向于使用触发器(插入/更新/删除),它将完整的行(之前和之后)放入“归档/审核”表中并添加他们想要记录的任何“元数据”...这样我的以应用程序为中心的数据模型就不会受到应用程序/SP等的污染,并且没有应用程序/用户可以访问敏感的记录/审计信息...
I don't know much about SQL Server but when confronted with such in an Oracle scenario I tend to employ triggers (insert/update/delete) which take the complete row (before and after) into an "archive/audit" table and add whatever "metadata" they want logged along with it... this way my app-centric data model won't get poluted regarding applications/SPs etc. and no app/user has access to that sensitive logging/auditing information...