事务处理

数据库事务将一系列修改组合在一起,以一种方式要么完成所有修改,要么一个都不修
改。经典使用事实的例子是两个银行账户间的现金交易。基本逻辑很简单。
account1.deposit(100)
account2.withdraw(100)
在Active Record 中,我们使用transaction()方法来执行一个块,这是一个特殊的数
据库事务处理的上下关联的段落。这个块的结尾,事务处理被提交,更新数据库,除非块中
有异常抛出,一旦出现异常,所有的改变将被回滚,数据库的状态还是没有改变。因为事务
处理位于数据库连接的上下文环境中。我们必须用一个Active Record 类做为一个被调来来
调用它们。像这样写
Account.transaction do
account1.deposit(100)
account2.withdraw(100)
end
让我们来试试事务处理。先创建一个新的数据库表。因为我们使用MySQL,我们就用
InnoDB 的存储引擎来创建表,这是支持事务处理的。
create table accounts (
id int not null auto_increment,
number varchar(10) not null,
balance decimal(10,2) default 0.0,
primary key (id)
) type=InnoDB;
接着,我们将定义一个简单的银行账户类。个类定义实例方法desposit()存钱,
withdraw()方法取钱。它也提供一些基本的确认—对这个特定账户类型,balance 不可能为
负数。
class Account < ActiveRecord::Base
def withdraw(amount)
adjust_balance_and_save(-amount)
end
def deposit(amount)
adjust_balance_and_save(amount)
end
private
def adjust_balance_and_save(amount)
self.balance += amount
save!
end
def validate
errors.add(:balance, "is negative") if balance < 0
end
end
让我们看看helper 方法,adjust_ablance_and_save()。第一行简单地更新balance 字
段。然后这个方法试着使用save!方法保存model。(记住如果对象不能被保存,save!会引发
一个异常。我们使用这个异常来通知事务是否发生错误。)
现在让我们写在两个账户转账代码。它很直白。
peter = Account.create(:balance => 100, :number => "12345")
paul = Account.create(:balance => 200, :number => "54321")
Account.transaction do
paul.deposit(10)
peter.withdraw(10)
end
我们检查数据库,的确,现金被交易成功了。
mysql> select * from accounts;
+----+--------+---------+
| id | number | balance |
+----+--------+---------+
| 5 | 12345 | 90.00 |
| 6 | 54321 | 210.00 |
+----+--------+---------+
我们再向前一步。试着转账350 美元,确认有效性的规则就会起作用。让我们试试。
peter = Account.create(:balance => 100, :number => "12345")
paul = Account.create(:balance => 200, :number => "54321")
Account.transaction do
paul.deposit(350)
peter.withdraw(350)
end
当我们运行它时,我们会在控制台得到一个异常报告。
validations.rb:652:in ‘save!': ActiveRecord::RecordInvalid
from transactions.rb:36:in ‘adjust_balance_and_save'
from transactions.rb:25:in ‘withdraw'
: :
from transactions.rb:71
看看数据库,我们可看到数据没有被更改。
mysql> select * from accounts;
+----+--------+---------+
| id | number | balance |
+----+--------+---------+
| 7 | 12345 | 100.00 |
| 8 | 54321 | 200.00 |
+----+--------+---------+
但是这里有个陷阱在等着你。事务处理可以避免数据库发生不一致的情况,但是model
对象又该如何呢?让我们看看对于它们会发生什么,我们必须截获异常来允许程序继续处理。
peter = Account.create(:balance => 100, :number => "12345")
paul = Account.create(:balance => 200, :number => "54321")
begin
Account.transaction do
paul.deposit(350)
peter.withdraw(350)
end
rescue
puts "Transfer aborted"
end
puts "Paul has #{paul.balance}"
puts "Peter has #{peter.balance}"
结果让人惊讶。
Transfer aborted
Paul has 550.0
Peter has -250.0
虽然数据库仍保持原样,但我们的model 对象却更新了。这是因为Active Record 不能
跟踪不同对象的更新前后的状态--事实上它也不可能,因为没有简单的办法知道哪个model
是在事务处理当中。我们可以调整这个,通过明白的告诉transaction()方法,把model 作
为一个参数输入才行。
peter = Account.create(:balance => 100, :number => "12345")
paul = Account.create(:balance => 200, :number => "54321")
begin
Account.transaction(peter, paul) do
paul.deposit(350)
peter.withdraw(350)
end
rescue
puts "Transfer aborted"
end
puts "Paul has #{paul.balance}"
puts "Peter has #{peter.balance}"
这次我们看到models 最终都没有改变。
Transfer aborted
Paul has 200.0
Peter has 100.0
我们可通过将转账功能移到Account 类中来整理一下这个代码。因为一个转账包含两个
单独的帐户,它们彼此不能互相驱动,我们要让它成为一个类方法,以接受两个account 对
象作为参数。注意在类方法内我们怎样来简化调用transaction()方法。
class Account < ActiveRecord::Base
def self.transfer(from, to, amount)
transaction(from, to) do
from.withdraw(amount)
to.deposit(amount)
end
end
end
用这个被定义的方法,我们的程序也干净多了。
peter = Account.create(:balance => 100, :number => "12345")
paul = Account.create(:balance => 200, :number => "54321")
Account.transfer(peter, paul, 350) rescue puts "Transfer aborted"
puts "Paul has #{paul.balance}"
puts "Peter has #{peter.balance}"
Transfer aborted
Paul has 200.0
Peter has 100.0
但是让事务处理代码自动恢复对象的状态有一个不足--你不能获得在确认期间得到任何
被添加的错误信息。无效的对象将不会被保存,事务处理将回滚所有的东西。但没有简单的
访法知道曾经发生了什么错误。

[color=red]内建的事务处理[/color]
当我们讨论父表和子表时,我们说当你要保存一个父表的记录时,Active Record 会注
意存储所有依赖的子表记录。这会有多个SQL 语句执行(一个是为父表,而每个子表都有sql
语句)。很显然,这种改变也是原子性的,但直到目前为止,我们都没有使用事务来保存这
样的相关对象。
Active Record 已经做得不错,它在一个事务处理中把所有的更新和插入操作包装到
save()(删除是destroy())。这些操作要么写成功,要么什么数据都不写入数据库。只有
在你管理多个SQL 语句时,你才需要显式的事务处理。
[color=red]
多数据库事务处理[/color]
在rails 中,怎样跨越多个不同数据库同步事务处理?
当前的回答是你不能。Rails 不支持分布的两阶段提交。
但是你可能通过嵌套事务来模仿这种效果。记住那个事务与数据库连接相关,并且连接
与model 相关。所以如果acconts 表在一个数据库中,并且用户在另一个数据库中,你可以
将同样的事情做两次来模仿些事务。例如,
User.transaction(user) do
Account.transaction(account) do
account.calculate_fees
user.date_fees_last_calculated = Time.now
user.save
account.save
end
end
这也只是一种尽可能解决办法。It is possible that the commit in the users database
might fail (perhaps the disk is full), but by then the commit in the accounts
database has completed and the table has been updated. This would leave the
overall transaction in an inconsistent state. It is possible (if not pleasant)
to code around these issues for each individual set of circumstances, but for
now, you probably shouldn’t be relying on Active Record if you are writing
applications that update multiple databases concurrently.
源码地址: https://pan.quark.cn/s/a4b39357ea24 欧姆龙触摸屏编程软件MPTST 5.02是专门为欧姆龙品牌的工业触摸屏而研发的编程解决方案,它赋予用户在直观界面上构建、修改以及排错触摸屏应用程序的能力。 该软件在工业自动化领域具有可替代的地位,特别是在生产线监视、设备操控以及人机互动系统中发挥着核心作用。 欧姆龙MPTST(Machine Process Terminal Software Touch)5.02版本配备了多样化的功能,旨在应对同种类的触摸屏项目要求。 以下列举了若干核心特性:1. **图形化编程**:MPTST 5.02采用图形化的编程模式,允许用户借助拖拽动作来设计屏幕布局,设定按钮、滑块、指示灯等组件,显著简化了编程流程,并提升了工作效率。 2. **兼容性**:该软件能够适配欧姆龙的多个触摸屏产品线,包括CX-One、NS系列、NJ/NX系列等,使用户可以在同一个平台上完成对同硬件的编程任务。 3. **数据通信**:MPTST 5.02具备与PLC(可编程逻辑控制器)进行数据交互的能力,通过将触摸屏作为操作界面,实现生产数据的显示与输入,以及设备状态的监控。 4. **报警与事件管理**:软件中集成了报警和事件管理机制,可以设定多种报警标准,一旦达到预设条件,触摸屏便会展示对应的报警提示,助力操作人员迅速做出响应。 5. **模拟测试**:在设备实际连接之前,MPTST 5.02支持用户进行脱机模拟测试,以此验证程序的正确性与稳定性。 6. **项目备份与恢复**:为了防止数据遗失,MPTST 5.02提供了项目文件的备份及还原功能,对于多版本控制与团队协作具有显著价值。 7. **多语言支持**:针对全球化的应...
本资源包为流体力学与化学传质交叉领域的研究提供了一套完整的数值模拟解决方案,重点针对湍流条件下通道内溶解物质的输运与分布规律进行定量分析。该工具集专为高等院校理工科专业的教育与科研需求设计,尤其适合计算机科学、电子工程及数学等相关学科的本科生在完成课程项目、综合设计或学位论文使用。 软件环境兼容多个版本的MatLAB平台,包括2014a、2019b及后续的2024b发行版,确保了在同实验室或个人计算环境中的可移植性。资源包内预置了经过验证的示例数据集,用户可直接调用主程序执行计算,显著降低了初始学习成本,使初学者能够迅速掌握基本操作流程。 代码架构采用模块化与参数驱动设计。所有关键物理参数(如流速、扩散系数、边界条件等)均集中于独立的配置模块,用户无需深入底层算法即可灵活调整计算条件,从而高效模拟多种湍流溶解场景。程序逻辑结构清晰,各功能段均配有详尽的说明注释,既阐述了数值方法的理论依据,也解释了关键步骤的实现意图,便于使用者理解模型构建过程并进行针对性修改。 在学术训练方面,本工具能够帮助学生将抽象的流体动力学与传质理论转化为可视化的数值实验结果,深化对湍流混合、浓度边界层等概念的理解。对于毕业设计或专题研究,其参数化框架支持用户嵌入自定义模型,开展创新性数值实验,为深入研究复杂流动中的溶解机制提供可靠的技术支撑。 总体而言,该MATLAB分析工具集通过结构化的代码设计、完备的案例支持与广泛的版本兼容性,为流体溶解现象的数值研究提供了一个高效、可扩展的计算平台,兼具教学示范与科研探索的双重价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值