MariaDB BIGINT UNSIGNED 值超出范围

MariaDB BIGINT UNSIGNED value is out of range

我一直在阅读有关此错误的信息,但找不到解决此错误的方法。 我确实有这句话每小时的时间表:

 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`))'

这是创建 table:

 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;

已添加:

像这样显示变量'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)

谢谢。

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

您使用的是哪个 MariaDB 版本?

你看过这个吗?

Error handling

In MySQL and MariaDB before 5.3 wrong arguments to UNIX_TIMESTAMP() returned 0. Starting from MariaDB 5.3 we return NULL for wrong arguments to UNIX_TIMESTAMP().

Compatibility

As you can see in the examples above, UNIX_TIMESTAMP(constant-date-string) returns in MariaDB 5.3 a timestamp with 6 decimals while MariaDB 5.2 and MySQL returns it without decimals. This can cause a problem if you are using UNIX_TIMESTAMP() as a partitioning function. You can fix this by using FLOOR(UNIX_TIMESTAMP(..)) or changing the date string to a date number, like 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)

避免减法,只在时间戳中工作:

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

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

这个'composite'索引可能有助于提高性能:

INDEX(acctstarttime, acctsessiontime, AcctStopTime)

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