我们的 Teamcenter(西门子的软件)经常运行数小时甚至数天的交易。就好像他们被遗忘了一样。甚至有 20 多个交易运行时间超过一个小时,甚至 20 小时。它们极大地填充了临时数据库,并且通常不会自行终止(必须被杀死)。我们的 Teamcenter 集成商说没关系,因为有些“翻译”过程需要很长时间。但是让事务运行这么长时间是否正确?
谢谢
我们的 Teamcenter(西门子的软件)经常运行数小时甚至数天的交易。就好像他们被遗忘了一样。甚至有 20 多个交易运行时间超过一个小时,甚至 20 小时。它们极大地填充了临时数据库,并且通常不会自行终止(必须被杀死)。我们的 Teamcenter 集成商说没关系,因为有些“翻译”过程需要很长时间。但是让事务运行这么长时间是否正确?
谢谢
在调试程序时,我需要经常删除一个Postgresql的数据库,然后重新创建它。
为方便起见,我想在单个命令行中执行此操作,如下所示:
psql -c "DROP DATABASE my_db; CREATE DATABASE my_db;"
但我得到一个错误:
错误:DROP DATABASE 不能在事务块内运行
有什么办法可以做到吗?谢谢!
今天尝试恢复自定义转储文件时,我在 Windows server 2019 机器上遇到了一个奇怪的 PostgreSQL ( v.13.8 )。
以下命令有效:
pg_restore -d postgres://postgres@localhost:5432/postgres --no-owner --no-privileges --create --clean --role=<myuser> --if-exists inputfile.backup 2> inputfile.log
但只需将--single-transaction
选项添加到命令行,就会引发错误:
pg_restore -d postgres://postgres@localhost:5432/postgres --no-owner --no-privileges --single-transaction --create --clean --role=<myuser> --if-exists inputfile.backup 2> inputfile.log
但我可以在日志文件中阅读:
pg_restore: error : options « -c/--clean » and « -a/--data-only » cannot be used together.
我什至没有使用-a
旗帜……这很奇怪,不是吗?
我已经阅读了pg_restore doc,尤其是关于--single-transaction
选项的段落,但它并没有说太多,(例如关于潜在的隐式-a
标志):
--单笔交易
将还原作为单个事务执行(即将发出的命令包装在 BEGIN/COMMIT 中)。这可确保所有命令都成功完成,或者不应用任何更改。此选项意味着 --exit-on-error。
任何人都可以告诉我使用此选项时到底发生了什么?
我有一个要调试的应用程序,它对 MySQL 数据库执行几十个操作。这些操作在单个事务中执行。在特定断点进行调试时,我需要知道数据库的状态。
mysql
我可以使用常用的CLI 工具登录 MySQL 服务。我看到正在进行的交易:
mysql> SELECT * FROM information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 325090
trx_state: RUNNING
trx_started: 2022-09-14 12:10:32
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 30
trx_mysql_thread_id: 26
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 10
trx_lock_structs: 26
trx_lock_memory_bytes: 1128
trx_rows_locked: 43
trx_rows_modified: 4
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
trx_schedule_weight: NULL
1 row in set (0.01 sec)
作为一种解决方法,我可以向应用程序代码添加查询。但是,这需要我在运行应用程序之前知道要运行哪个查询,然后为要运行的每个查询重新编译应用程序。有一个开放的 CLI 来调试会非常有帮助。
该数据库是在 Debian 上运行的 MySQL 8.0。
我是交易新手。当我阅读“事务信息系统”一书时,提到 B-tree 使用键范围锁定来保证可串行化。这是真的所有对关系的访问都必须通过相同的 B-tree 进行以保证可序列化吗?
如果我理解正确,如果访问是通过不同的索引,则无法保证可序列化。请参阅以下示例。
假设同一个关系上有两个索引,分别是B树和哈希索引,并且有两个事务。
首先,一个事务使用散列索引读取关系,例如,fetchkey(16)
使用键获取(当前不存在的)记录16
并且找不到匹配项。由于散列没有键范围锁定,它不能锁定下一个键。然后,另一个事务通过 B-tree 插入一条键为 '16' 的记录。插入将成功,导致幻像。
我用一个非常有用的答案问了这个问题:
如何对跨多个表的结构进行唯一性约束?
Erwin Brandstetter 的回答表明了这一点:
WITH ins_string_properties AS (
INSERT INTO string_properties (source_id, name, value)
VALUES (gen_random_uuid(), 'slug', 'hello-world')
ON CONFLICT DO NOTHING -- to silence unique violation errors
RETURNING source_id
)
, ins_objects AS (
INSERT INTO objects (id, type)
SELECT o.id, o.type
FROM ins_string_properties isp -- always 0 or 1 rows
CROSS JOIN LATERAL (
VALUES
(isp.source_id , 'baz')
, (gen_random_uuid(), 'foo')
, (gen_random_uuid(), 'bar')
) o(id, type)
RETURNING id, type
)
INSERT INTO object_properties (source_id, name, value_id)
SELECT io1.id, io2.type, io2.id
FROM ins_objects io1
JOIN ins_objects io2 ON io1.type = 'foo' AND io2.type = 'bar'
OR io1.type = 'bar' AND io2.type = 'baz'
;
我只是在学习 CTE,但答案是:
READ COMMITTED
在具有默认事务隔离的并发写入负载下也是安全的。
我将在 CockroachDB 中使用它,他们似乎建议避免READ COMMITTED
使用它SERIALIZABLE
。
我可以将此查询与. 一起使用吗SERIALIZABLE
,或者如果不可以,为什么不 / 必须修改什么以使其与SERIALIZABLE
. 这些事务级别对我来说是新的,过去我主要使用 PostgreSQL 和 Ruby on Rails ORM,所以没有深入研究 SQL。只是尝试使用SERIALIZABLE
CockroachDB 推荐的默认事务隔离级别,并且不确定我是否/何时可以/不能使用它,并且不确定这种情况。
这就是我对READ COMMITTED
vs.的了解SERIALIZABLE
。
假设我有一个类似这样的模式系统:
create table objects {
uuid id;
string type;
}
create table object_properties {
uuid id;
uuid source_id; // the object which has this property
string name; // the property name
uuid value_id; // the property value object
}
// ...and tables for each primitive data type
create table string_properties {
uuid id;
uuid source_id; // the object which has this property
string name; // the property name
string value; // the property value string
}
然后我想创建这个对象:
{
type: 'foo',
bar: {
type: 'bar',
baz: {
type: 'baz',
slug: 'hello-world'
}
}
}
那是:
// objects
id | type
123 | foo
234 | bar
345 | baz
// object_properties
source_id | name | value_id
123 | bar | 234
234 | baz | 345
// string_properties
source_id | name | value
345 | slug | hello-world
slug: hello-world
如果以结尾的树不存在,我只想创建这个“对象树” 。我怎样才能做到最好?我可以很容易地做到这一点,首先进行查询,检查对象是否存在,如果不存在则创建它。但这是一个查询,然后是一个插入。有可能两个进程同时进入,都进行查询,都成功,然后都进行插入。我怎样才能防止这种情况?请注意,我目前在事务中都发生了每个独立的查询+插入,因此每个事务都有查询后跟插入。
或者update
第一笔交易的内部是否可以从第二笔交易的“外部”读取?我正在使用 PostgreSQL / CockroachDB,这是一种“未提交读取”的设置吗?
所以我认为我有一个相当复杂的系统,它正在开始出现。写出所有表格太复杂了,但这里是一个简短的描述。
基本上我正在为帖子创建一个像 StackOverflow 这样的徽章系统。你有这些类型的表:
然后假设您“更新帖子”。这是发生的事情:
您如何在 PostgreSQL 中适当地完成此任务?在我的具体情况下,似乎有大约 10 个表被查询,至少 5 个表被修改(创建或更新记录)。所有这些在理论上应该是原子的,在一个事务中,但是打包到一个事务中似乎很多,特别是如果你有这些“事件”在一秒钟内多次出现。
我能想到的唯一可能解决这个问题的初始方法是 使用队列和后台作业。上述每个步骤都将在事务之外按顺序完成,步骤之间可能存在时间间隔。所以会有一个中间状态,事情是不一致的。但最终(理论上似乎),队列将运行并重试直到成功,并进入正确的状态。这应该怎么做?
如果不是,是否可以在每个事件上进行单一交易的复杂性?我不知道,我不认为实施徽章和这些计数器的解决方案会变得如此复杂,但每个事件都有很多需要考虑和做的事情。基于您构建可扩展数据库系统的专业知识,我正在寻找任何指向正确方向的指针。
假设这个系统一定是这么复杂,因为我在理论上真的是在问如何处理复杂的事务需求。也就是说,如果您知道一种对徽章系统进行建模的理想方法,那会很高兴知道,但不会真正解决问题的主要部分。感谢您的帮助!
目前,就我的目的而言,一切都可以被认为适合单台机器,而不是分布在多个数据库中。
是否可以使用单个线程回滚事务?
我试图找到这个问题的答案,但我找不到提供参考的答案。我读到了回滚机制。见下文:
如果您回滚事务,引擎将开始向后扫描日志以查找您的事务完成的工作记录并撤消工作:当它找到从 A 到 B 的更新记录时,会将值更改回 A。插入将通过删除插入的行来撤消。通过插入该行将撤消删除。这在事务日志逻辑架构和预写事务日志中进行了描述。
这是高级解释,确切的内部细节是如何发生的,外行没有记录,也不受您的检查或更改。
回滚事务比执行它需要更长的时间。有几个原因。
现在的问题是,如何在各种场景中测试这些操作消耗了多少资源(单/多线程)?
据我所知,声称有一个线程。但是,我找不到任何证据来支持这种说法。
如果执行单线程操作,是否可以将行为更改为多线程?相反的呢?
我想查看正在进行事务的表中的数据。我将以这个超级简单的临时表为例:
SELECT 5 AS NUMBER INTO ##temptable
我将创建一个事务来插入一个编号为 10 的新行:
BEGIN TRAN;
INSERT INTO ##temptable
SELECT 10 AS Number
WAITFOR DELAY '00:00:20';
COMMIT TRAN;
现在,如果我打开一个新查询并执行常规选择语句,我将不会得到任何结果,轮子将一直旋转,直到事务提交。我可以改为将隔离级别设置为已提交读:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
我希望这会返回承诺的数字 5,而不是未承诺的数字 10,但我再次得到一个纺车。我想这不是它的工作原理。
如果我将隔离级别设置为未提交:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
这成功地从表中返回两个数字。
我仍然有一个问题,因为我想像这样在事务内部创建表:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRAN;
SELECT 5 AS NUMBER INTO ##temptable
INSERT INTO ##temptable
SELECT 10 AS Number
WAITFOR DELAY '00:00:20';
COMMIT TRAN;
在这种情况下,如果我尝试从表中读取,即使隔离级别设置为未提交,我也会再次得到一个旋转的轮子。
有没有办法从正在进行的事务中创建的表中读取?