我在netezza中有12个存储过程。我使用来自 shell 脚本的 nzsql 命令调用这些过程。我想并行运行这些过程以提高吞吐量。我该怎么做?
可序列化
如果存储过程不影响相同的表,则可以从 bash 分叉调用:
nzsql -Atc "call sp1();" &
nzsql -Atc "call sp2();" &
nzsql -Atc "call sp3();" &
...
wait
查看有关分叉的其他答案。
不可序列化
如果存储过程影响相同的表,则需要在受影响的连接或事务中关闭可序列化性。我没有在存储过程中执行此操作(您可能做不到(,但这应该有效:
nzsql -Atc "set serializable = false; call sp1();" &
nzsql -Atc "set serializable = false; call sp2();" &
nzsql -Atc "set serializable = false; call sp3();" &
...
wait
有关可序列化隔离级别的详细信息,请参阅文档。你将负责确保存储过程正在修改的数据不会以某种方式发生冲突,因为你会得到脏读。
为了详细说明@Jeremy Fortune的答案,在三种情况下,系统中止事务以保持可序列化性:
- 一个
update
或delete
语句与另一个语句同时运行 在同一表上update
或delete
语句。 - 两个并发事务,每个事务执行一个
SELECT FROM
和一个INSERT INTO
同一张表。这可以作为自插入语句或任意顺序的多个语句发生。请注意,最多支持向同一表执行 31 个并发插入操作,前提是从同一表中选择的并发插入次数不超过一个。 - 两个并发事务,其中第一个事务从表1
selects
和updates
、inserts
或deletes
表2,而第二个事务从表2selects
,updates
、inserts
或deletes
表 1.
您可以在此处阅读有关它的更多信息。
但是,序列化事务可以在失败之前处于队列中,并且系统会自动重试,直到它在 X 分钟后全部超时,X 由系统变量定义serialization_queue_timeout
。
但是,这仅适用于隐式事务(没有BEGIN
和COMMIT
块的事务(,并且大多数存储过程事务都是显式事务(这也是使用存储过程的优点,如果出现问题,所有内容都会回滚,除非您使用了放置在存储过程中某处AUTOCOMMIT ON
选项(,这不会让您利用序列化队列。