Rails datetime类型在mysql数据库中的精度问题

在我的博客网站开发过程中,我在开发环境使用sqlite3,而在生产环境则使用性能更好的mysql。一直以来我也觉得没什么,因为rails会屏蔽所有的数据库差异。但这样也带来一些问题,其中一个就是schema.rb的版本控制问题。Rails建议对此文件进行版本控制,这样可以更清楚的看到数据库版本的变动。但由于开发和生产环境使用的数据库不一致,导致每次rake db:migrate后schema.rb都会变化,开发环境和生产环境的这个文件版本不一致(由于数据库的不同),将测试环境的schema.rb传到版本控制显然不好,但是不传的话总是提示有文件未提交感觉很不好。

经过权衡决定在测试环境也使用mysql,并且将测试数据也导入到新的mysql数据库。数据库不一致的另一个问题是我在迁移时发现的,不同的数据库还是有差异的,而且还影响到测试案例的成功与否,其中一个问题就是这次要重点介绍的datetime类型的精度问题。

datetime类型是rails在generate model时自动生成的,如果执行

$ bin/rails generate model Product name:string description:text 

会生成一个迁移文件如下:

#file name: db/migrate/20160501090706_create_products.rb
class CreateProducts < ActiveRecord::Migration
  def change
    create_table :products do |t|
      t.string :name
      t.text :description
 
      t.timestamps null: false
    end
  end
end 

其中 t.timestamps null: false会生成2个字段created_at,updated_at,其schema.rb中的

#file name : schema.rb
#...
    t.datetime "created_at"
    t.datetime "updated_at"
#...

这种datetime类型的字段是作为时间戳使用的,在sqlite3中为6位精度,如2016-05-01 11:28:38.860909,这没有问题。但是换为使用mysql就有问题了,datetime 类型在mysql中默认精度只到秒,这显然不能满足要求,秒级的时间戳是没有意义的。在网上找了很多资料,有很多比较陈旧,下面把我测试通过的解决方法记录一下,方便大家参考1 2

在Rails 4.2的Release Notes有下面一句话:

Added support for fractional seconds for MySQL 5.6 and above

可以看出Rails 4.2已经支持日期精度功能,关于mysql的fractional seconds功能可以参考 mysql reference.

我们在Rails 4.2+应用中应该如何使用此功能呢?可以通过添加migrate文件来解决,具体如下:

 bin/rails g migration ChangeDatetimeLimitForMysql 

在生成的文件中修改如下:(下面只以修改一个表为例,多个表修改方法类似)

# file name: db/migrate/20160501090706_change_datetime_limit_for_mysql.rb
# mysql 5.6.4以上的版本支持分数精度(fractional seconds),默认mysql精度只到秒
# limit 置为 6 精确到微妙;如将limit 修改为 3 则精确到毫秒

class ChangeDatetimeLimitForMysql < ActiveRecord::Migration
  def up
    change_column :comments, :created_at, :datetime, limit: 6
    change_column :comments, :updated_at, :datetime, limit: 6

     #...
  end
  
  def down
    change_column :comments, :created_at, :datetime
    change_column :comments, :updated_at, :datetime

    #...
  end
end 

然后执行rake db:migrate即可,这样之后新增修改的记录的时间戳都会精确到微秒。注意测试环境也需要执行rake db:test:prepare使其生效。

[注]:此方案适用于Rails 4.2+,mysql 5.6.4+.

参考资料:

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《ITechLib》

非root用户启动apache、mysql

近期在组内搭建了一个wiki平台,方便知识整理分享。但由于没有自己控制的服务器,只能使用一台公共的服务器。root用户需要申请才能使用,网上很多教程都是针对root用户的,包括安装启动。其实apache、mysql从设计之初就是支持非root用户使用的,用户可以根据自己需要指定端口、数据存放地址以及其他一些配置信息。下面简单介绍一下非root用户启动需要做哪些事情(安装为了简单跟管理员申请了一下root权限)

1.启动apache1

可以使用指定的httpd.conf文件来启动apache,命令如下:

/usr/local/apache2/bin/apachectl -f /your/path/httpd.conf   -k start

1.1 修改端口

直接执行上面命令可能会报错,因为apache默认绑定端口位80,而非root用户是不允许使用1024以下的端口的,可以在httpd.conf中修改。

Listen 80 #修改为--> Listen 9001

如果改后端口外部不可访问可以试试8080等常用端口,或者跟管理员申请开发新配置的端口。

1.2 修改用户组

在httpd.conf中找到User/Group

User _www
Group _www

修改为你自己的组,如下所示:

User flyingbird
Group flyingbird

1.3 修改html的根目录

有两个地方要改,分别如下:(DocumentRoot,Directory)

DocumentRoot "/Library/WebServer/Documents"
<Directory "/Library/WebServer/Documents">

上面两个地址改为你要放网站的地址,两者要保持一致。

1.4 加载必须的mod

可以直接在httpd.conf中找下看,常用的mod一般都有,只要把注释去掉即可。

1.5 修改PidFile和日志路径

可以直接在httpd.conf中修改,包括PidFile、ErrorLog、ServerRoot等,如果不必要尽量不要修改。

1.6 停止apache

/usr/local/apache2/bin/apachectl -f /your/path/httpd.conf -k stop

2. 启动mysql2

mysql比较特殊,也可以支持非root安装启动(一般用户),但更通用的做法是使用mysql用户启动。

2.1 安装启动

在通过yum安装好后,yum install mysql mysql-server,可以登录mysql用户,如果没有的话可以先建一个:

# adduser mysql
# passwd mysql 设置密码

然后登录mysql用户并启动

/etc/init.d/mysqld start

停止:

/etc/init.d/mysqld stop

默认是采用/etc/my.cnf文件配置的,可以根据需要修改其中的配置

2.2 修改root用户密码

$ mysql -u root

mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd');
mysql> SET PASSWORD FOR ''@'host_name' = PASSWORD('newpwd'); 

参考资料:

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《ITechLib》