如果我有一个数百万行的表并且我运行一个更新 50k 行的事务,这对性能有什么影响?
假设它的索引正确,它应该不会花费很长时间,但是锁定了哪些行以及该表的使用如何受到影响?
- 在事务开始之后和结束之前是否可以读取事务期间正在更新的行?
- 事务期间未更新的行是否可以在事务开始之后和结束之前读取?
- 如果另一个事务开始尝试更改之前未完成的事务正在更改的行,那么该事务会在开始时失败还是在尝试提交之后失败(假设冲突)?
我的问题是 Postgres 9.3;我假设有变化。
如果我有一个数百万行的表并且我运行一个更新 50k 行的事务,这对性能有什么影响?
假设它的索引正确,它应该不会花费很长时间,但是锁定了哪些行以及该表的使用如何受到影响?
我的问题是 Postgres 9.3;我假设有变化。
在事务开始之后和结束之前是否可以读取事务期间正在更新的行?
是的,在 Postgres 中读取不会阻塞写入,写入不会阻塞读取。Postgres 文档指出:
事务期间未更新的行是否可以在事务开始之后和结束之前读取?
是的。
如果另一个事务开始尝试更改之前未完成的事务正在更改的行,那么该事务会在开始时失败还是在尝试提交之后失败(假设冲突)?
这取决于事务隔离级别以及您是否发出依赖于读取或盲写的写入。使用默认级别Read Committed,第二个事务必须等到第一个事务完成写入。在更高的事务级别中,其中一个事务可能会因序列化错误而中止。
您实际上可以通过运行两个
psql
会话自己尝试:第 1 节:
正如您将看到的,会话 2 将被会话 1 阻止。只有当会话 1 提交时,会话 2 才能继续。
postgres 文档还包含有关在使用更高事务级别时如何避免阻塞和序列化失败的性能建议。
1 是
可以读取正在更新的行并将显示旧值,直到事务提交。
2 是
未写入的行不受影响。
3 否或是取决于。
如果另一个事务持有一个需要死锁的锁,则将清除其中一个事务,否则另一个事务将暂停,直到该事务提交或回滚。并且在那个阶段它将退出并出现错误或被允许继续。
出于这个原因,最好将长期交易保持在最低限度。