如果我有一个数百万行的表,并且运行一个更新 50k 行的事务,那么这会对性能产生什么影响?
假设它的索引正确,应该不会花很长时间,但是哪些行被锁定以及该表的使用如何受到影响?
我的问题是针对 Postgres 9.3 的;我认为存在差异。
在我们的 Python 应用程序上看到查询性能并不令人满意,该应用程序运行多个SQLAlchemy core用于访问 PostgreSQL 9.2 数据库的进程。我们可能有大约 100-200 个或更多并发进程对数据库执行查询。
我们没有像pgpoolII或pgbounce当前安装的连接池系统。
我测试了查询,可以采取的顺序1-10秒,从我们的应用程序,它运行在何时psql将最多20毫秒。
我们认为这个问题与并发连接有关,特别是因为上述行为,并且因为我们在访问系统中的不同表时看到这些性能下降。但是,我们对此并不确定,可以很容易地接受替代建议或解决方案。
处理来自单个数据库服务器的多个进程的并发连接的常用方法是什么,以使查询能够快速执行?
我有一个关于交易的相当基本的问题。
假设Account有一个列金额的表。现在我们有以下代码:
BEGIN
$amount = SELECT amount FROM ACCOUNT WHERE id = 123;
$amount = $amount - 100;
UPDATE ACCOUNT SET amount = $amount WHERE id = 123;
COMMIT
Run Code Online (Sandbox Code Playgroud)
现在,如果此代码段由 2 个事务并发运行,T1 和 T2 会发生什么?
我知道在 MySQL 中默认隔离级别是REPEATABLE READ.
所以假设最初的金额是 500。
那么当 2 笔交易完成时,最终的金额是 300 还是 100?
我的意思是当他们开始从表中读取时,我猜这是一个共享锁。
当一个人更新表时,它会获得一个排他锁吗?那么另一笔交易会发生什么?它会继续处理它开始时“查看”的数量,即 500?
拇指的任何规则work_mem,maintenance_work_mem,shared_buffer等,为的是不预期的并发连接,并且正在做大量的聚集功能的数据库?
我是一名社会科学家,不希望将 Postgres 用作供多个用户共享的数据库,而是作为我自己的工具来操作海量数据集(我有 50 亿条交易记录(csv 中为 600gb)并想退出唯一用户对、估计单个用户的聚合等)。
我可以在网上找到的所有关于调优的建议(这个、这个、这个等等)都是为那些预计会有大量并发连接的人写的。对于单独使用数据库进行数据操作的人来说,任何人都有基本的经验法则吗?
更新: - 这也意味着几乎没有写入,除了根据主表中的选择创建新表。(显然这很重要——谢谢欧文!)
更新 2: - 我在 Windows 8 VM 上使用 16gb ram、SCSI VMware HD 和 3 个内核(如果这很重要)。
[短的]
我有以下情况:用户A尝试将数据DA插入数据库。要检查是否A允许用户插入DA,我需要运行查询并进行一些计算。我遇到的问题是,当我进行计算时,另一个用户 ( B) 也尝试将数据插入到数据库中。现在,假设两个用户在插入新数据之前都读取了计算所需的信息,那么他们可能都被清除插入,而来自用户的数据A将禁止用户B插入,从而使数据库处于不一致状态。
如何在 Azure SQL 数据库 V12 中解决这种并发问题?
[详细的]
用户插入的数据是时间间隔的开始和结束,例如start: 6:00, end: 7:00。要求是不能有时间间隔重叠。这意味着区间start: 6:00, end: 9:00和start: 5:00, end: 6:00不能同时存在。目前我正在做的是检查是否有任何行与用户尝试使用以下查询插入的新间隔重叠:
SELECT COUNT(*) FROM [Table1] WHERE Start <= attempEnd && End >= attemptStart
Run Code Online (Sandbox Code Playgroud)
现在,问题是多个用户可能试图插入一个间隔,而这些新间隔可能相互重叠。但是,在上面的查询运行时,此信息可能不可用,这会导致插入重叠间隔。
如何在 Azure SQL 数据库 V12 中解决这种并发问题?
我有两个表 ( SJob& SJobDependent),我需要为存储过程中的某些逻辑加入它们。它们都有一列 ( job)以一对多关系连接它们- 一条SJob记录对应零个或多个SJobDependent记录。
这是我的 SQL 查询:
-- Return any records that are active and have no unsatisfied dependencies.
SELECT * FROM SJob
LEFT JOIN SJobDependent
ON SJob.job = SJobDependent.job
AND SJobDependent.satisfied = 0
WHERE SJobDependent.jobDependentID IS NULL
AND SJob.state = 'active'
Run Code Online (Sandbox Code Playgroud)
这是SQL Server Studio的实际执行计划:
由于代码的编写方式:
-- Return any records that are active and have no unsatisfied dependencies.
SELECT * FROM SJob
LEFT JOIN SJobDependent
ON …Run Code Online (Sandbox Code Playgroud) 我有一个需要执行的命令列表,所有这些命令都包含在我命名为 的表中myQueue。这个表有点独特,因为一些命令应该组合在一起,以便它们的执行按顺序执行,而不是并发执行,因为同时执行它们会导致不需要的数据工件和错误。因此,队列不能以典型的FIFO / LIFO方式分类,因为出队顺序是在运行时确定的。
总结一下:
myQueue将充当命令队列(其中出队顺序在运行时确定)UPDATE而不是 a执行的,DELETE因为此表用于所述命令的历史性能报告我目前的方法是通过sp_getapplock/sp_releaseapplock调用使用显式互斥逻辑来迭代这个表。虽然这按预期工作,但该方法会生成足够的锁定,因此在任何给定时间都无法在队列上迭代大量工作线程。在阅读了 Remus Rusanu关于该主题的优秀博客文章后,我决定尝试使用表格提示,希望可以进一步优化我的方法。
我将包含下面的测试代码,但总结一下我的结果,使用表提示和消除对sp_getapplock/ 的调用的缺点sp_releaseapplock最多会导致以下三种不良行为:
不过,从积极的方面来说,当代码适应死锁时(例如,重试当前包含的违规操作),不使用sp_getapplock/sp_releaseapplock且不会表现出不良行为的方法 2 和 3 的执行速度至少是两倍,如果不是更快的话.
我希望有人会指出我没有正确构建出列语句,这样我仍然可以继续使用表提示。 如果那不起作用,那就这样吧,但我想看看它是否可以做到同样的事情。
可以使用以下代码设置测试。
该myQueue表的创建和人口与命令类似于够我的工作量:
CREATE TABLE myQueue
(
ID INT IDENTITY (1,1) PRIMARY KEY CLUSTERED,
Main INT, …Run Code Online (Sandbox Code Playgroud) 在表中Orders,我存储了我们从所有商店收到的订单。由于一个订单可以有多个行,列中有OrderID和OrderLineID
在那里OrderID可以复制,但OrderLineID必须是一个顺序中是唯一的。
由于订单可以修改,存储过程首先检查收到的订单OrderLineID是否已经存在于表中,然后决定插入还是更新。为此,我们:
然后是主表:
IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID ......)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID
Run Code Online (Sandbox Code Playgroud)
或者该MERGE功能是否提供更好的性能/控制?
但问题如下:
由于线路问题/服务器繁忙等,Order消息(或修改)可能会被多次发送,我们不知道按哪个顺序发送。因此,为了避免Order修改后到达,从而覆盖修改,我们添加了一个时间列:
IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID AND LastModified<@CreatedTime
Run Code Online (Sandbox Code Playgroud)
这样,如果后一条消息比前一条消息旧,则对表没有影响。
但是,消息及其修改可能会在很短的时间内发送两次(或更多),以至于后一条消息在保存前一条消息之前到达。因此,对于存储过程的两次执行,它 …
到目前为止,我读过的所有谈论事务的书籍都展示了涉及多个 SQL 语句的场景。
但是单个语句又如何呢?他们的隔离程度如何?标准中是否有指定?或者它取决于 RDBMS 和隔离级别?
让我举几个例子。
UPDATE table SET value = value + 1 WHERE id = 1;
这是一个复合read-update-write操作。read并行事务可以改变和write操作之间的值吗?有些书指出,在大多数RDBMS中,此操作是原子的(在多线程编程意义上) 。
SELECT * FROM table t1 JOIN table t2 USING (id);
如果表很大(或者查询会有一些复杂的过滤子句),在某些隔离级别上,列t1.*和t2.*列是否可能因并行更新而有所不同?
SELECT * FROM table1 WHERE id IN (SELECT t_id FROM table2);
table1执行子选择后是否有可能删除一些记录?(这里我假设table2.t_id引用table1.id具有级联删除功能。)
热膨胀系数...
还可以提供有用手册的链接,这些手册充分解释了交易的所有细节。
我读过《深入了解 MySQL 和 PostgreSQL 中的隔离级别》和《读取现象》,尤其是“Postgres 中的序列化异常”部分。我想我已经理解了那里描述的问题,但是我很难判断它何时会在我的应用程序中发生。
是否只有使用 SUM/COUNT 这样的聚合函数才能在 Postgres 中获得序列化异常?如果不是,我还需要注意什么?
concurrency ×10
postgresql ×4
sql-server ×4
transaction ×2
consistency ×1
innodb ×1
locking ×1
mysql ×1
queue ×1