我想在PostgreSQL中对表进行大量更新,但我不需要在整个操作中维护事务完整性,因为我知道我正在更改的列不会被写入或读取更新.我想知道psql控制台中是否有一种简单的方法可以更快地完成这些类型的操作.
例如,假设我有一个名为"orders"的表,有3500万行,我想这样做:
UPDATE orders SET status = null;
Run Code Online (Sandbox Code Playgroud)
为避免被转移到offtopic讨论,让我们假设3500万列的所有状态值当前都设置为相同(非空)值,从而使索引无用.
此语句的问题是需要很长时间才能生效(仅因为锁定),并且所有更改的行都将被锁定,直到整个更新完成.此更新可能需要5个小时,而类似
UPDATE orders SET status = null WHERE (order_id > 0 and order_id < 1000000);
Run Code Online (Sandbox Code Playgroud)
可能需要1分钟.超过3500万行,执行上述操作并将其分成35块只需要35分钟,节省了4小时25分钟.
我可以用脚本进一步分解它(在这里使用伪代码):
for (i = 0 to 3500) {
db_operation ("UPDATE orders SET status = null
WHERE (order_id >" + (i*1000)"
+ " AND order_id <" + ((i+1)*1000) " + ")");
}
Run Code Online (Sandbox Code Playgroud)
此操作可能仅在几分钟内完成,而不是35分钟.
所以这归结为我真正的要求.我不想写一个怪异的脚本来分解操作,每次我想做这样一个大的一次性更新.有没有办法在SQL中完成我想要的东西?
我有一个观察者,我注册了一个after_commit回调.如何判断它是在创建或更新后被触发的?我可以通过询问来判断某个项目已被销毁item.destroyed?但是#new_record?因为该项目已保存而无法正常工作.
我打算通过添加after_create/ after_update并执行类似于@action = :create内部的操作并检查@actionat 来解决它after_commit,但似乎观察者实例是单例,我可能只是在它到达之前覆盖一个值after_commit.所以我以一种更丑陋的方式解决了这个问题,根据after_create/update上的item.id将动作存储在地图中,并在after_commit上检查它的值.真的很难看
还有其他方法吗?
正如@tardate所说,transaction_include_action?虽然它是一种私有方法,但它是一个很好的指示,并且在观察者中它应该被访问#send.
class ProductScoreObserver < ActiveRecord::Observer
observe :product
def after_commit(product)
if product.send(:transaction_include_action?, :destroy)
...
Run Code Online (Sandbox Code Playgroud)
不幸的是,该:on选项在观察者中不起作用.
只要确保你测试你的观察者的地狱(test_after_commit如果你使用use_transactional_fixtures 寻找宝石)所以当你升级到新的Rails版本时,你会知道它是否仍然有效.
(测试3.2.9)
我现在使用ActiveSupport :: Concern代替Observers并after_commit :blah, on: :create在那里工作.
Django 1.6提出@transaction.atomic了1.5中交易管理改革的一部分.
我有一个由Django管理命令调用的函数,该命令又由cron调用,即在这种情况下没有HTTP请求触发事务.片段:
from django.db import transaction
@transaction.commit_on_success
def my_function():
# code here
Run Code Online (Sandbox Code Playgroud)
在上面的代码块中,commit_on_success使用单个事务完成所有工作my_function.
更换是否@transaction.commit_on_success与@transaction.atomic在相同的行为结果?@transaction.atomic docs说:
原子性是数据库事务的定义属性.atomic允许我们创建一个代码块,在该代码块中保证数据库的原子性.如果代码块成功完成,则更改将提交到数据库.如果存在异常,则回滚更改.
我认为它们会导致相同的行为; 正确?
我们都使用DB::transaction()多个插入查询.这样做,是应该try...catch放在里面还是包裹它?甚至有必要包括一个事件try...catch在出现问题时会自动失败的情况吗?
try...catch包装交易的示例:
// try...catch
try {
// Transaction
$exception = DB::transaction(function() {
// Do your SQL here
});
if(is_null($exception)) {
return true;
} else {
throw new Exception;
}
}
catch(Exception $e) {
return false;
}
Run Code Online (Sandbox Code Playgroud)
相反,DB::transaction()包装尝试...抓住:
// Transaction
$exception = DB::transaction(function() {
// try...catch
try {
// Do your SQL here
}
catch(Exception $e) {
return $e;
}
});
return is_null($exception) ? true : false;
Run Code Online (Sandbox Code Playgroud)
或者只是一个没有尝试的交易......捕获
// Transaction only
$exception …Run Code Online (Sandbox Code Playgroud) 我想知道什么时候使用爆炸!用于保存和更新记录的版本?我已阅读并听说你不需要他们,如果你只是一个保存记录或更新一个属性,如果你确信没有什么应该出问题,或总是使用他们的控制之外.我想我很擅长有多个东西被保存然后出现问题然后数据库中的数据不完整.我正在开发的当前Rails项目已完成50%以上,目前不包含任何刘海.我有一些自定义方法,我在更新或创建多个记录的模型中调用,并担心它们是否应该在某种交易中.
很抱歉,如果这看起来很分散,但我只是想弄清楚如何正确使用ActiveRecord中的保存功能,让我的生活更轻松,最后一点也没有压力.谢谢你的时间.
当我尝试调用包含SELECT语句的存储过程时,我收到以下错误:
该操作对交易状态无效
这是我的电话结构:
public void MyAddUpdateMethod()
{
using (TransactionScope Scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using(SQLServer Sql = new SQLServer(this.m_connstring))
{
//do my first add update statement
//do my call to the select statement sp
bool DoesRecordExist = this.SelectStatementCall(id)
}
}
}
public bool SelectStatementCall(System.Guid id)
{
using(SQLServer Sql = new SQLServer(this.m_connstring)) //breaks on this line
{
//create parameters
//
}
}
Run Code Online (Sandbox Code Playgroud)
我在问题中创建了另一个与同一数据库的连接的问题吗?
Connection.setTransactionIsolation(int) 警告:
注意:如果在事务期间调用此方法,则结果是实现定义的.
这提出了一个问题:如何在JDBC中开始事务?很清楚如何结束交易,但不知道如何开始交易.
如果a Connection在事务内部启动,我们应该如何在事务Connection.setTransactionIsolation(int)外部调用以避免特定于实现的行为?
我正在尝试使用命令模式来允许我的Web层在单个事务的上下文中使用Hibernate实体(从而避免延迟加载异常).但是,我现在对如何处理交易感到困惑.
我的命令调用使用@Transactional注释注释的服务层方法.这些服务层方法中的@Transactional(readOnly=true)一些是只读的- 例如- 并且一些是读/写的.
我的服务层公开了一个命令处理程序,它执行代表Web层传递给它的命令.
@Transactional
public Command handle( Command cmd ) throws CommandException
Run Code Online (Sandbox Code Playgroud)
我假设我正确地使命令处理程序的handle()方法成为事务性的.这就是混乱的来源.如果命令的实现调用多个服务层方法,命令处理程序无法知道命令中调用的操作是只读,读/写还是组合两个.
我不明白传播在这个例子中是如何工作的.如果我要创建该handle()方法readOnly=true,那么如果该命令随后调用带有注释的服务层方法会发生什么@Transactional(realOnly=false)?
我希望更好地理解这一点并欢迎您的评论......
安德鲁
我正在尝试使用新的async/await功能来异步处理数据库.由于一些请求可能很长,我希望能够取消它们.我遇到的问题是TransactionScope显然有一个线程亲和力,似乎在取消任务时,它Dispose()会在一个错误的线程上运行.
具体来说,打电话时.TestTx()我得到以下AggregateException含InvalidOperationException上task.Wait ():
"A TransactionScope must be disposed on the same thread that it was created."
Run Code Online (Sandbox Code Playgroud)
这是代码:
public void TestTx () {
var cancellation = new CancellationTokenSource ();
var task = TestTxAsync ( cancellation.Token );
cancellation.Cancel ();
task.Wait ();
}
private async Task TestTxAsync ( CancellationToken cancellationToken ) {
using ( var scope = new TransactionScope () ) {
using ( var connection = new SqlConnection ( m_ConnectionString …Run Code Online (Sandbox Code Playgroud) 可以在事务中使用SQL"truncate table"命令吗?我正在创建一个应用程序,我的表有大量的记录.我想删除所有记录,但如果应用程序失败,我将回滚我的事务.删除每条记录需要很长时间.我想知道我是否使用截断表,我是否仍然可以回滚事务并在发生故障时恢复数据.我意识到truncate table不会将每个删除写入事务日志,但我想知道它是否将页面释放写入日志以便回滚工作.
transactions ×10
.net ×2
c# ×2
sql-server ×2
activerecord ×1
async-await ×1
database ×1
dblink ×1
django ×1
django-1.6 ×1
java ×1
jdbc ×1
laravel ×1
php ×1
plpgsql ×1
postgresql ×1
spring ×1
sql ×1
sql-update ×1
truncate ×1