MariaDB BIGINT UNSIGNED值超出范围

时间:2016-07-03 19:36:10

标签: mysql mariadb mysql-error-1064 freeradius

我一直在阅读有关此错误的内容,但无法找到解决此错误的方法。 我这句话每小时都有一个时间表:

 UPDATE radacct SET 
            radacct.AcctStopTime=NOW(),
            radacct.AcctTerminateCause='Stale-Session'
        WHERE ((UNIX_TIMESTAMP(NOW()) - (UNIX_TIMESTAMP(radacct.acctstarttime) + radacct.acctsessiontime)) > (60*6+60*6))
            AND (AcctStopTime = '0000-00-00 00:00:00' OR AcctStopTime IS NULL)

有时候我会收到这个错误:

 BIGINT UNSIGNED value is out of range in '(unix_timestamp(now()) - (unix_timestamp(`radius`.`radacct`.`acctstarttime`) + `radius`.`radacct`.`acctsessiontime`))'

这是创建表:

 CREATE TABLE `radacct` (
   `radacctid` bigint(21) NOT NULL AUTO_INCREMENT,
   `acctsessionid` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `acctuniqueid` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `username` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `groupname` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `realm` varchar(64) COLLATE utf8_unicode_ci DEFAULT '',
   `nasipaddress` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `nasportid` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
   `nasporttype` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `acctstarttime` datetime DEFAULT NULL,
   `acctupdatetime` datetime DEFAULT NULL,
   `acctstoptime` datetime DEFAULT NULL,
   `acctinterval` int(12) DEFAULT NULL,
   `acctsessiontime` int(12) unsigned DEFAULT NULL,
   `acctauthentic` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `connectinfo_start` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
   `connectinfo_stop` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
   `acctinputoctets` bigint(20) DEFAULT NULL,
   `acctoutputoctets` bigint(20) DEFAULT NULL,
   `calledstationid` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   `callingstationid` varchar(50) COLLATE utf8_unicode_ci NOT NULL      DEFAULT '',
   `acctterminatecause` varchar(32) COLLATE utf8_unicode_ci NOT NULL      DEFAULT '',
   `servicetype` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `framedprotocol` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `framedipaddress` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
   PRIMARY KEY (`radacctid`),
   UNIQUE KEY `acctuniqueid` (`acctuniqueid`),
   KEY `username` (`username`),
   KEY `framedipaddress` (`framedipaddress`),
   KEY `acctsessionid` (`acctsessionid`),
   KEY `acctsessiontime` (`acctsessiontime`),
   KEY `acctstarttime` (`acctstarttime`),
   KEY `acctinterval` (`acctinterval`),
   KEY `acctstoptime` (`acctstoptime`),
   KEY `nasipaddress` (`nasipaddress`),
   KEY `callingstationid` (`callingstationid`) USING BTREE
 ) ENGINE=InnoDB AUTO_INCREMENT=14270573 DEFAULT CHARSET=utf8      COLLATE=utf8_unicode_ci;

添加了:

SHOW变量LIKE'sql_mode'

'sql_mode','NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

新增2:

这是最终的查询,完美地建议@Rick James

 UPDATE radacct SET 
            radacct.AcctStopTime=NOW(),
            radacct.AcctTerminateCause='Stale-Session'
        WHERE (  NOW() - interval (60*6+60*6) second  >  radacct.acctstarttime + interval radacct.acctsessiontime second  )
            AND (AcctStopTime = '0000-00-00 00:00:00' OR AcctStopTime IS NULL)

感谢。

2 个答案:

答案 0 :(得分:1)

这不是答案,但我不能在评论中对其进行格式化。

您使用的是哪个MariaDB版本?

你见过这个吗?

  

错误处理

     

在MySQL和MariaDB之前5.3对UNIX_TIMESTAMP()的错误参数   返回0.从MariaDB 5.3开始,我们返回NULL表示错误   UNIX_TIMESTAMP()的参数。

     

<强>兼容性

     

正如您在上面的示例中所看到的,   UNIX_TIMESTAMP(constant-date-string)在MariaDB 5.3中返回   时间戳有6位小数,而MariaDB 5.2和MySQL则返回它   没有小数。如果您正在使用,这可能会导致问题   UNIX_TIMESTAMP()作为分区函数。您可以使用以解决此问题    FLOOR(UNIX_TIMESTAMP(..))或将日期字符串更改为日期   号码,如20080101000000。

     

https://mariadb.com/kb/en/mariadb/unix_timestamp/

尝试此操作以找到错误的行

检查一下 - 发出错误

SELECT CAST(0 AS UNSIGNED) - 1;

将sql_mode设置为

SET sql_mode='NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_UNSIGNED_SUBTRACTION';

再次检查 - 没有错误

SELECT CAST(0 AS UNSIGNED) - 1;

查询以查找错误的行

SELECT *
FROM radacct
WHERE ((UNIX_TIMESTAMP(NOW()) - (UNIX_TIMESTAMP(radacct.acctstarttime) + radacct.acctsessiontime)) < 0
AND (AcctStopTime = '0000-00-00 00:00:00' OR AcctStopTime IS NULL)

答案 1 :(得分:1)

避免减法并仅在时间戳中起作用:

WHERE  radacct.acctstarttime + INTERVAL radacct.acctsessiontime SECOND
     < NOW() - INTERVAL 12 MINUTE

(在我看来,它更具可读性)

这个'复合'索引可能有助于提升绩效:

INDEX(acctstarttime, acctsessiontime, AcctStopTime)

如果遇到性能问题,请考虑规范化广泛但重复的列。