在现有架构中,我仅为其中一个表引入审计跟踪/里程碑支持。为了讨论这个问题,我们将使用简化的玩具示例来更好地说明问题。
DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 12/1/9999 | 1
现在,当每次{id} 1的department
记录的更新请求进入时,系统会执行以下操作。基本上每次更新都是INSERT
- 将现有记录的MODIFIED_TS
更改为UPDATE
次请求,最新记录的MODIFIED_TS
始终保持为12/1/9999
(aka { {1}} TIMESTAMP)
说更新ID = 1记录,其中名称已更改,以下是db。中的内容。
INFINITY
现在假设存在DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 11/22/2015 | 1
1 | "XYZ" | 11/22/2015 | 12/1/9999 | 2
表,其中EMPLOYEE
作为外键。请注意,DEPT_ID
表没有审计跟踪要求,因此那里没有EMPLOYEE
时间戳或INFINITY
概念。 VERSION
表格如下所示
EMPLOYEE
对于与DEPT有FK关系的EMPLOYEE而言,一切都很好,其中DEPT之前有ID作为PK。现在EMPLOYEE
ID | NAME | AGE | DEPT_ID
1 | "John" | 31 | 1
表的PK被更改为复合PK(ID,VERSION)
在DEPARTMENT
表的这些模式更改为其数据创建auit跟踪之后,DEPARTMENT
中的FK将不得不以某种方式创建FK,不仅EMPLOYEE
而且还DEPT_ID
包含INFINITY
个MODIFIED_TS
记录的DEPT
时间戳(EMPLOYEE
),因为DEPT
将始终引用最新的EMPLOYEE
记录(要求)
更改DEPT
表的FK以指向Nov 9 02:16:59 ip-172-31-6-86 [service_variant=lms][openedx.core.djangoapps.user_api.helpers][env:sandbox] ERROR [ip-172-31-6-86 2138] [helpers.py:75] - An unexpected error occurred when calling 'request_password_change' with arguments '(u'ariestiyansyah.rizky@gmail.com', 'xxx.org', True)' and keyword arguments '{}': ValueError('incomplete format',)
Traceback (most recent call last):
File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 46, in _wrapped
return func(*args, **kwargs)
File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/user_api/accounts/api.py", line 403, in request_password_change
use_https=is_secure
File "/edx/app/edxapp/edx-platform/common/djangoapps/student/forms.py", line 78, in save
email = loader.render_to_string(email_template_name, context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/loader.py", line 171, in render_to_string
return t.render(Context(dictionary))
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 140, in render
return self._render(context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
return self.nodelist.render(context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 823, in render
bit = self.render_node(node, context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 837, in render_node
return node.render(context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/defaulttags.py", line 31, in render
output = self.nodelist.render(context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 823, in render
bit = self.render_node(node, context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/template/base.py", line 837, in render_node
return node.render(context)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/templatetags/i18n.py", line 151, in render
result = result % data
ValueError: incomplete format
Nov 9 02:16:59 ip-172-31-6-86 [service_variant=lms][root][env:sandbox] ERROR [ip-172-31-6-86 2138] [exceptions.py:9] - Uncaught exception from <class 'django.core.handlers.wsgi.WSGIHandler'>
Traceback (most recent call last):
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 109, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/views/decorators/http.py", line 41, in inner
return func(request, *args, **kwargs)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/student_account/views.py", line 153, in password_change_request_handler
request_password_change(email, request.get_host(), request.is_secure())
File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 76, in _wrapped
raise api_error(msg)
UserAPIInternalError: An unexpected error occurred when calling 'request_password_change' with arguments '(u'ariestiyansyah.rizky@gmail.com', 'xxx.org', True)' and keyword arguments '{}': ValueError('incomplete format',)
Nov 9 02:16:59 ip-172-31-6-86 [service_variant=lms][django.request][env:sandbox] ERROR [ip-172-31-6-86 2138] [base.py:213] - Internal Server Error: /account/password
Traceback (most recent call last):
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 109, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/views/decorators/http.py", line 41, in inner
return func(request, *args, **kwargs)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/student_account/views.py", line 153, in password_change_request_handler
request_password_change(email, request.get_host(), request.is_secure())
File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/user_api/helpers.py", line 76, in _wrapped
raise api_error(msg)
UserAPIInternalError: An unexpected error occurred when calling 'request_password_change' with arguments '(u'ariestiyansyah.rizky@gmail.com', 'xxx.org', True)' and keyword arguments '{}': ValueError('incomplete format',)
表中最新记录的最佳方法是什么?
答案 0 :(得分:0)
这是一个可怕的数据建模黑客,可以解决你的问题;不要在家里试试......
由于部门的PK是{id,modified_ts},员工的FK也必须是复合的(或者它可以指向另一组唯一的列)。 所以解决方案是给它想要的东西:一个具有恒定值'无穷大'的列。 ('infinity'是postgres中日期和时间戳的有效值,您不需要发明自己的哨兵值)
CREATE TABLE department
( id INTEGER NOT NULL
, name varchar
, created_ts timestamp
, modified_ts timestamp
, version integer not null default 0
, PRIMARY KEY (id, modified_ts)
);
INSERT INTO department (id, name, created_ts, modified_ts, version) VALUES
(1 , 'ABC', '2015-11-20' , '2015-11-22' , 1) ,
(1 , 'XYZ', '2015-11-22' , 'infinity' , 2) ;
-- CREATE UNIQUE INDEX ON department (id) WHERE modified_ts = 'infinity'::timestamp;
-- Now assume there is an existing EMPLOYEE table with DEPT_ID as a foreign key. Note that EMPLOYEE table doesn't have an audit trail requirement so there is no INFINITY timestamp or VERSIONing concept there. EMPLOYEE table looks like as below
CREATE TABLE employee
( id INTEGER NOT NULL PRIMARY KEY
, name varchar
, age integer not null default 0
, modified_ts timestamp NOT NULL DEFAULT 'infinity'::timestamp CHECK (modified_ts = 'infinity'::timestamp)
, dept_id INTEGER NOT NULL
, FOREIGN KEY (id,modified_ts)
REFERENCES department(id, modified_ts)
);
INSERT INTO employee(id ,name,age,dept_id) VALUES
(1 , 'John' , 31 , 1);
DEFERRABLE INITIALLY DEFERRED