当前位置: 首页 > 面试题库 >

MySQL为什么不支持毫秒/微秒精度?

夏侯昊明
2023-03-14
问题内容

因此,我刚刚发现MySQL中最令人沮丧的错误。

显然,该TIMESTAMP字段及其支持功能不支持比秒更高的精度!

所以我正在使用PHP和Doctrine,我真的需要那些微秒(我正在使用actAs: [Timestampable]属性)。

我发现我可以使用一个BIGINT字段来存储值。但是学说会增加毫秒吗?我认为它只是将NOW()分配给该字段。我还担心通过代码散布的日期操作功能(在SQL中)会中断。

我还看到了有关编译UDF扩展的内容。这是不可接受的,因为我或将来的维护者会升级,烦恼,更改不见了。

有没有人找到合适的解决方法?


问题答案:

我找到了解决方法!它非常干净,不需要更改任何应用程序代码。这适用于Doctrine,也可以应用于其他ORM。

基本上,将时间戳存储为字符串。

如果日期字符串格式正确,则比较和排序有效。当传递日期字符串时,MySQL时间函数将截断微秒部分。如果不需要微秒精度,则可以date_diff

SELECT DATEDIFF('2010-04-04 17:24:42.000000','2010-04-04 17:24:42.999999');
> 0

SELECT microsecond('2010-04-04 17:24:42.021343');
> 21343

我最终写了一个MicroTimestampable实现此目标的类。我只是actAs:MicroTimestampable用MySQL和Doctrine来注释我的字段,等等,时间精度。

Doctrine_Template_MicroTimestampable

class Doctrine_Template_MicroTimestampable extends Doctrine_Template_Timestampable
{
    /**
     * Array of Timestampable options
     *
     * @var string
     */
    protected $_options = array('created' =>  array('name'          =>  'created_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'options'       =>  array('notnull' => true)),
                                'updated' =>  array('name'          =>  'updated_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'onInsert'      =>  true,
                                                    'options'       =>  array('notnull' => true)));

    /**
     * Set table definition for Timestampable behavior
     *
     * @return void
     */
    public function setTableDefinition()
    {
        if ( ! $this->_options['created']['disabled']) {
            $name = $this->_options['created']['name'];
            if ($this->_options['created']['alias']) {
                $name .= ' as ' . $this->_options['created']['alias'];
            }
            $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']);
        }

        if ( ! $this->_options['updated']['disabled']) {
            $name = $this->_options['updated']['name'];
            if ($this->_options['updated']['alias']) {
                $name .= ' as ' . $this->_options['updated']['alias'];
            }
            $this->hasColumn($name, $this->_options['updated']['type'], null, $this->_options['updated']['options']);
        }

        $this->addListener(new Doctrine_Template_Listener_MicroTimestampable($this->_options));
    }
}

Doctrine_Template_Listener_MicroTimestampable

class Doctrine_Template_Listener_MicroTimestampable extends Doctrine_Template_Listener_Timestampable
{
    protected $_options = array();

    /**
     * __construct
     *
     * @param string $options 
     * @return void
     */
    public function __construct(array $options)
    {
        $this->_options = $options;
    }

    /**
     * Gets the timestamp in the correct format based on the way the behavior is configured
     *
     * @param string $type 
     * @return void
     */
    public function getTimestamp($type, $conn = null)
    {
        $options = $this->_options[$type];

        if ($options['expression'] !== false && is_string($options['expression'])) {
            return new Doctrine_Expression($options['expression'], $conn);
        } else {
            if ($options['type'] == 'date') {
                return date($options['format'], time().".".microtime());
            } else if ($options['type'] == 'timestamp') {
                return date($options['format'], time().".".microtime());
            } else {
                return time().".".microtime();
            }
        }
    }
}


 类似资料:
  • 问题内容: 我想将毫秒转换为秒(例如,将1500ms转换为1.5s,或将500ms转换为0.5s)。 并不是最好的方法:我正在寻找一种从除法运算中获取余数的方法,因此我可以简单地添加余数。 问题答案: 当然,您只需要: 无需分别手动执行这两个部分- 您只需要浮点运算即可(使用字面量)即可。(我假设您的值是某种形式的整数。) 请注意,和一样,您可能无法准确表示结果。如果您想 精确地 将100ms表示

  • 我在代码中使用倒计时。问题是,倒计时不准确。onTick方法并不总是每秒执行一次,它可能需要几毫秒的时间。当试图基于millisUntilFinished执行某项任务时,这会成为一个问题。当我的20秒计时器超过10秒时,我正在尝试登录: 以下是相关代码: 这里出现了一个问题,因为countDownTimer可能永远不会有millisUntilFinished==10000,它可能等于1001,因此

  • 问题内容: 我正在使用golang的go-ping(https://github.com/sparrc/go- ping )库进行无特权的ICMP ping。 通过运行此命令,我得到的延迟是毫秒,抖动是微秒。我想让两个单位都等于毫秒,因此当我执行或(将微秒转换为毫秒)时,得到的抖动是纳秒级的:(。有什么办法可以使延迟和抖动都达到相同的单位毫秒。 问题答案: 编号为 是具有作为其基础类型的类型,该类

  • 我从GPS接收机接收到一个时间戳,它以秒后的微秒时间表示:

  • 这个问题我已经研究了一段时间,但我只能得到秒数,下面是给我的说明:编写一个程序,从代表纳秒数的标准输入中读取一个非负整数。然后,程序编写一行输出,给出等效的天、小时、分钟、秒、毫秒、微秒和纳秒的数量。例如,输入为123456789123456789。则输出为:123456789123456789纳秒等于1428天、21小时、33分钟、9秒、123毫秒、456微秒和789纳秒。这是我写的: }

  • 我现在用SDL2编程。所有这些都可以正常工作,但我对方法有一个问题。通常,它应该以毫秒为单位返回应用程序的总时间,但它总是在大部分时间返回值0,有时返回值1。 我用标志初始化SDL。 以下代码的问题是循环太快,因此增量时间小于1 ms。是否有方法实现更高的精度?