- 浏览: 2678093 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
再谈ActiveRecord、MySQL和transaction
第一篇:ActiveRecord如何与MySQL交互
我们自定义的MyModel继承于ActiveRecord::Base类
这个connection是什么东西?让我们一步步往下看
可以看到MyModel的一些方法都在base.rb里实现为connection对象相关的方法
如果我们使用的是MySQL数据库,则这里的connection为ActiveRecord::ConnectionAdapters::MysqlAdapter对象
这是在Rails初始化时做的:
而MysqlAdapter继承于AbstractAdapter,AbstractAdapter又include了DatabaseStatements所以:
这里的MysqlAdapter.@connection在mysql_adapter.rb的mysql_connection方法里初始化了:
继续追踪:
至此,Rails自带的MySQL Adapter了解清楚了。
第二篇:ActiveRecord对MySQL的事务封装
首先看看MySQL的事务控制(摘自MySQL5.1参考手册):
START TRANSACTION或BEGIN语句可以开始一项新的事务
COMMIT可以提交当前事务,使变更成为永久变更
ROLLBACK可以回滚当前事务,取消其变更
SET AUTOCOMMIT语句可以禁用或启用默认的autocommit模式,用于当前连接
默认情况下,MySQL采用autocommit模式运行
这意味着,当您执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中
如果您正在使用一个事务安全型的存储引擎(如InnoDB, BDB或NDB簇),则您可以使用以下语句禁用autocommit模式:SET AUTOCOMMIT=0
通过把AUTOCOMMIT变量设置为零,禁用autocommit模式之后,您必须使用COMMIT把变更存储到磁盘中,或着如果您想要忽略从事务开始进行以来做出的变更,使用ROLLBACK
使用START TRANSACTION,autocommit仍然被禁用,直到您使用COMMIT或ROLLBACK结束事务为止。然后autocommit模式恢复到原来的状态
开始追踪:
这就是Rails里所谓的“隐式事务”,给你安排好了
这表示ActiveRecord对save,save!和destroy方法都包上了事务,而create、update、delete等方法最终都是调用save、save!和destroy方法
追踪:
看下database_statements.rb里的transaciton方法:
马上又回到mysql_adapter.rb里对transaction打开、提交、回滚的实现:
execute即Mysql.query,上面提到了。
那么为啥ActiveRecord的transaction不支持嵌套呢?
还是看transaction.rb:
原来,Rails每次遇到调用transaction方法时,看看当前线程里open transaction的次数:
1, 如果有多次,则调用connection.transaction(false, &block)
2, 如果为零次,则调用connection.transaction(true, &block)
而database_statements.rb里的transaciton方法根据true or false参数来判断是否重复open transaction
这样,Rails遇到最外层的transaction打开后,就不会再打开内部的transaction了,这也是手动写多层嵌套transaction时只有最外层的起作用的原因
至此,Rails对transaction的封装了解清楚。
第一篇:ActiveRecord如何与MySQL交互
我们自定义的MyModel继承于ActiveRecord::Base类
MyModel < ActiveRecord::Base MyModel.find_xxx -> find_by_sql -> connection.select_all(sql) MyModel.create_xxx -> connection.insert(sql) MyModel.update_xxx -> connection.update(sql) MyModel.destroy -> connection.delete(sql)
这个connection是什么东西?让我们一步步往下看
可以看到MyModel的一些方法都在base.rb里实现为connection对象相关的方法
如果我们使用的是MySQL数据库,则这里的connection为ActiveRecord::ConnectionAdapters::MysqlAdapter对象
这是在Rails初始化时做的:
environment.rb的Rails::Initializer.run -> initializer.rb的process方法 -> initializer.rb的initialize_database方法 -> ActiveRecord::Base.establish_connection(connenction_specification.rb里对ActiveRecord::Base添加该方法和connection方法) -> mysql_adapter.rb的mysql_connection方法 -> mysql.rb的real_connect方法 -> TCPSocket::new/UNIXSocket::new
而MysqlAdapter继承于AbstractAdapter,AbstractAdapter又include了DatabaseStatements所以:
MyModel < ActiveRecord::Base MyModel.find_xxx -> find_by_sql -> DatabaseStatements.select_all(sql) -> MysqlAdapter.select(sql) -> MysqlAdapter.execute(sql) -> MysqlAdapter.@connection.query(sql) MyModel.create_xxx -> MysqlAdapter.insert(sql) -> MysqlAdapter.execute(sql) -> MysqlAdapter.@connection.query(sql) MyModel.update_xxx -> MysqlAdapter.update(sql) -> MysqlAdapter.execute(sql) -> MysqlAdapter.@connection.query(sql) MyModel.destroy -> DatabaseStatements.delete(sql) -> MysqlAdapter.execute(sql) -> MysqlAdapter.@connection.query(sql)
这里的MysqlAdapter.@connection在mysql_adapter.rb的mysql_connection方法里初始化了:
require_mysql mysql = Mysql.init mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslkey] ConnectionAdapters::MysqlAdapter.new(mysql, logger, [host, username, password, database, port, socket], config)
继续追踪:
@connection.query(sql) -> real_query(sql) -> command(sql) -> Net.read/write -> socket.read/write
至此,Rails自带的MySQL Adapter了解清楚了。
第二篇:ActiveRecord对MySQL的事务封装
首先看看MySQL的事务控制(摘自MySQL5.1参考手册):
引用
START TRANSACTION或BEGIN语句可以开始一项新的事务
COMMIT可以提交当前事务,使变更成为永久变更
ROLLBACK可以回滚当前事务,取消其变更
SET AUTOCOMMIT语句可以禁用或启用默认的autocommit模式,用于当前连接
默认情况下,MySQL采用autocommit模式运行
这意味着,当您执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中
如果您正在使用一个事务安全型的存储引擎(如InnoDB, BDB或NDB簇),则您可以使用以下语句禁用autocommit模式:SET AUTOCOMMIT=0
通过把AUTOCOMMIT变量设置为零,禁用autocommit模式之后,您必须使用COMMIT把变更存储到磁盘中,或着如果您想要忽略从事务开始进行以来做出的变更,使用ROLLBACK
使用START TRANSACTION,autocommit仍然被禁用,直到您使用COMMIT或ROLLBACK结束事务为止。然后autocommit模式恢复到原来的状态
开始追踪:
# transactions.rb def self.included(base) base.extend(ClassMethods) base.class_eval do [:destroy, :save, :save!].each do |method| alias_method_chain method, :transactions end end end
这就是Rails里所谓的“隐式事务”,给你安排好了
这表示ActiveRecord对save,save!和destroy方法都包上了事务,而create、update、delete等方法最终都是调用save、save!和destroy方法
追踪:
transactions.rb的transaction -> connection.transaction -> MysqlAdapter.transaction(没有) -> AbstractAdapter.transaciton(没有) -> DatabaseStatements.transaction
看下database_statements.rb里的transaciton方法:
def transaction(start_db_transaction = true) transaction_open = false begin if block_given? if start_db_transaction begin_db_transaction transaction_open = true end yield end rescue Exception => database_transaction_rollback if transaction_open transaction_open = false rollback_db_transaction end raise end ensure commit_db_transaction if transaction_open end
马上又回到mysql_adapter.rb里对transaction打开、提交、回滚的实现:
def begin_db_transaction #:nodoc: execute "BEGIN" rescue Exception # Transactions aren't supported end def commit_db_transaction #:nodoc: execute "COMMIT" rescue Exception # Transactions aren't supported end def rollback_db_transaction #:nodoc: execute "ROLLBACK" rescue Exception # Transactions aren't supported end
execute即Mysql.query,上面提到了。
那么为啥ActiveRecord的transaction不支持嵌套呢?
还是看transaction.rb:
def transaction(*objects, &block) previous_handler = trap('TERM') { raise TransactionError, "Transaction aborted" } increment_open_transactions begin unless objects.empty? ActiveSupport::Deprecation.warn "Object transactions are deprecated and will be removed from Rails 2.0. See http://www.rubyonrails.org/deprecation for details.", caller objects.each { |o| o.extend(Transaction::Simple) } objects.each { |o| o.start_transaction } end result = connection.transaction(Thread.current['start_db_transaction'], &block) objects.each { |o| o.commit_transaction } return result rescue Exception => object_transaction_rollback objects.each { |o| o.abort_transaction } raise ensure decrement_open_transactions trap('TERM', previous_handler) end end private def increment_open_transactions #:nodoc: open = Thread.current['open_transactions'] ||= 0 Thread.current['start_db_transaction'] = open.zero? Thread.current['open_transactions'] = open + 1 end def decrement_open_transactions #:nodoc: Thread.current['open_transactions'] -= 1 end
原来,Rails每次遇到调用transaction方法时,看看当前线程里open transaction的次数:
1, 如果有多次,则调用connection.transaction(false, &block)
2, 如果为零次,则调用connection.transaction(true, &block)
而database_statements.rb里的transaciton方法根据true or false参数来判断是否重复open transaction
这样,Rails遇到最外层的transaction打开后,就不会再打开内部的transaction了,这也是手动写多层嵌套transaction时只有最外层的起作用的原因
至此,Rails对transaction的封装了解清楚。
评论
3 楼
hideto
2008-06-14
这是你写一个模拟JTA跨库操作的Ruby库的好机会
2 楼
javaeyename
2008-06-14
问一下,大家以前应该都是做java的吧,java里面有jta,rail里面有没有jta这个东西,或者第三方工具包也行。我找了没有发现。感觉现在的rail像是php,适合单数据库事务操作,跨库操作就麻烦很多!
1 楼
blackanger
2008-05-26
blog主题这么搞成这样,用ff看很晕的。。。
发表评论
-
用了TextMate才知道什么叫神级Editor
2011-03-09 04:51 57959一直用Eclipse作为开发Ruby和Java项目的IDE,但 ... -
Ruby使用OAuth登录新浪微博和豆瓣
2011-01-09 12:49 4433首先需要安装oauth这个gem包 gem install ... -
使用Passenger+nginx部署Rails
2010-12-28 15:12 50101. Install Passender gem instal ... -
markItUp+rdiscount搭建Rails下可视化Markdown编辑器
2010-12-21 17:48 5447markItUp是基于jQuery的可视化编辑器,支持Html ... -
Rails3 and MongoDB Quick Guide
2010-12-10 14:13 2753Install MongoDB Download: http: ... -
基于ruby-protobuf的rpc示例
2009-08-11 11:51 41481, 安装ruby-protobuf gem instal ... -
Ruby导出xls和csv的utf-8问题的解决
2009-02-04 15:05 6839数据库数据为utf-8格式,包括中文和拉丁文等等 导出文件xl ... -
URL/HTML/JavaScript的encode/escape
2009-01-04 13:03 9323最近经常被URL、HTML、JavaScript的encode ... -
各种排序的Ruby实现
2008-11-27 14:51 3994Θ(n^2) 1, Bubble sort def bu ... -
12月5日北京RoR活动!
2008-11-26 18:38 3017又是一年过去了,Rails在国内的发展势态良好,很多使用RoR ... -
Rails程序开发的最大问题是代码规范
2008-08-28 11:56 5515使用Rails开发大型复杂B2B应用一年了,这个项目目前开发人 ... -
Web开发大全:ROR版——推荐序
2008-07-09 00:39 2415来自http://www.beyondrails.com/bl ... -
深入ActionMailer,使用Sendmail发邮件
2008-07-03 11:41 3396来自: http://www.beyondrails.com/ ... -
Rails里如何结合ExceptionNotification配置gmail账户发邮件
2008-06-19 19:56 30801,安装ExceptionNotification rub ... -
使用coderay和railscasts样式进行代码高亮
2008-06-17 00:16 2395CodeRay是一个语法高亮的Ruby库,效率很不错。 Cod ... -
Capistrano试用
2008-06-16 19:05 19581,客户端机器安装Capistrano gem insta ... -
lighttpd真垃圾啊
2008-06-04 18:38 2530使用lighttpd+fcgi跑Rails程序,文件上传会si ... -
将gem变成plugin
2008-06-04 11:27 1801有什么样的需求就有什么样的对策 当vhost上的帐号没有ge ... -
在Rails里使用ReCaptcha添加验证码
2008-06-03 15:51 42661,去http://recaptcha.net/sign up ... -
Rails里给文件上传添加progress_bar
2008-05-27 17:00 2087文件上传很慢时,UI没有什么用户提示,这样让人很费解,所以我们 ...
相关推荐
只要您使用的是新适配器mysql2,pg或sqlite3,就可以与MySQL,PostgreSQL和SQLite一起使用。 支持所有ANSI SQL隔离级别::serializable,:repeatable_read,:read_committed,:read_uncommitted。 另请参阅 gem...
支持MySQL,PostgreSQL和SQLite。 例子 通过拯救ActiveRecord :: TransactionIsolationConflict并重试事务,gem自动工作。 安装 将此添加到您的Gemfile中: gem 'transaction_retry' 然后运行: bundle 它可以与...
以上就是Jfinal框架进行SQL数据库操作的一些基本知识,结合MySQL数据库,开发者可以高效地进行数据的存取和管理。在实际开发中,还需要考虑性能优化、安全性等问题,例如使用预编译的PreparedStatement来防止SQL注入...
与或一起使用时,将ruby 2.4、2.5和2.6的咨询锁定(mutexes)添加到ActiveRecord 4.2、5.x和6.0。 SQLite求助于文件锁定。 什么是“咨询锁”? 咨询锁是一种用于确保没有两个进程同时运行某个进程。 当咨询锁由您...
虽然这个示例没有使用ORM(Object-Relational Mapping)框架,但水晶有一些流行的ORM框架,如`Shards`和`ActiveRecord`,它们可以简化数据库操作,将数据模型映射到数据库表。 通过"crystal-mysql-crud-example"这个...
The samples of the release package all TESTED on Sql Server 2005 Express, MySql 5.0, SQLite 3, Access 2003, Firebird 2.1.0, PostgreSQL 8.3.3 and Oracle 10g express. Features: Linq support (need .net...
ActiveRecord::Base.transaction do # 执行语句 end ``` 4. **重试机制**:有时,这个错误可能是由于临时的网络问题或服务器繁忙导致的。在这种情况下,可以尝试添加一个重试机制,如果遇到错误,等待一段时间...
它支持多种数据库适配器,包括常见的MySQL、PostgreSQL和SQLite,这使得它具有广泛的适用性。 使用database_flusher时,开发人员通常需要在测试配置文件中设置相关的清理策略。例如,可以使用`DatabaseFlusher....
在实际开发中,Ruby-SQLite3也常常与ORM(对象关系映射)框架,如ActiveRecord(Rails的一部分)结合使用,以提供更加抽象和方便的数据操作接口。通过ActiveRecord,开发者可以使用Ruby对象来代表数据库中的记录,...
Anima允许您查询SQL和Stream类的数据库。 一种简单的DSL语法,支持多个数据库,与Java8集成良好,支持多个关系映射,并且是一种数据库操作工具。 特征 简单的DSL H2,MySQL,SQLite,PostgreSQL,Oracle,Sql...
在这里,可能会有如`Transaction`、`Income`和`Expense`这样的模型,用于代表财务交易、收入和支出。这些模型通常会与数据库中的表相对应,通过ActiveRecord库进行交互,例如定义属性、关联和验证规则。 接着,视...
@Transaction public void saveUser(User user) { user.save(); } ``` **6.7 Cache** - **功能**:缓存机制,提高应用性能。 - **示例**: ```java CacheKit.put("user", "id", user); ``` **6.8 ...
Ecto是Elixir的一个核心库,提供了一套用于处理数据存储、查询和验证的工具,类似于Ruby on Rails中的ActiveRecord。Ecto通过适配器机制支持多种数据库,包括MySQL、PostgreSQL以及我们的主角——SQL Server。 ### ...
GORM支持多种数据库,如MySQL、PostgreSQL、SQLite和SQL Server,允许开发者通过面向对象的方式处理数据库操作。 3. **安装GORM** 要在项目中使用GORM,首先需要通过`go get`命令安装GORM库: ``` go get -u ...