欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL decimal unsigned更新负数转化为0

程序员文章站 2022-07-03 14:56:25
今天在验证接口的并发问题时,把之前通过 redis 解决的并发压力转移到 mysql 上(redis 在 set 保存数据和数据过期需要去向数据库获取时存在时延,会存在空挡造成大并发多插入数据的风险;...

今天在验证接口的并发问题时,把之前通过 redis 解决的并发压力转移到 mysql 上(redis 在 set 保存数据和数据过期需要去向数据库获取时存在时延,会存在空挡造成大并发多插入数据的风险;由于有负载均衡,php 的信号量也无法用上,只好利用 mysql 的update 来解决并发,设置索引后速度也不慢,只是会承受压力)。发现在 update 一个字段(属性为 decimal unsigned),填入负值不会报错,会自动转化为 0。搜索了很久,是 my.cnf 中 strict_trans_tables 搞的鬼。

这时需要先了解 sql_mode

mysql服务器可以以不同的sql模式来操作,并且可以为不同客户端应用不同模式。这样每个应用程序可以根据自己的需求来定制服务器的操作模式。模式定义mysql应支持哪些sql语法,以及应执行哪种数据验证检查。这样可以更容易地在不同的环境中使用mysql,并结合其它数据库服务器使用mysql。你可以用--sql-mode="modes"选项启动 mysqld 来设置默认sql模式。如果你想要重设,该值还可以为空(--sql-mode ="")。你还可以在启动后用set [session|global] sql_mode='modes' 语句设置sql_mode变量来更改sql模式。设置 global变量时需要拥有super权限,并且会影响从那时起连接的所有客户端的操作。设置session变量只影响当前的客户端。任何客户端可以随时更改自己的会话 sql_mode值。

sql_mode 是用逗号(',')间隔开的一系列不同的模式。你可以用select @@sql_mode语句查询当前的模式。默认值是空(没有设置任何模式)。

主要重要sql_mode值为:

  ansi

  更改语法和行为,使其更符合标准sql。

  strict_trans_tables

  如果不能将给定的值插入到事务表中,则放弃该语句。对于非事务表,如果值出现在单行语句或多行语句的第1行,则放弃该语句。

  traditional

  make mysql的行为象“传统”sql数据库系统。该模式的简单描述是当在列中插入不正确的值时“给出错误而不是警告”。注释:一旦发现错误立即放弃insert/update。如果你使用非事务存储引擎,这种方式不是你想要的,因为出现错误前进行的数据更改不会“滚动”,结果是更新“只进行了一部分”。

  本手册指“严格模式”,表示至少strict _trans_tables或strict _all_tables被启用的模式。

  以下是 strict_trans_tables 和 strict_all_tables 两种模式的区别:

  对于事务表,当启用strict_all_tables或strict_trans_tables模式时,如果语句中有非法或丢失值,则会出现错误。语句被放弃并滚动。

  对于非事务表,如果插入或更新的第1行出现坏值,两种模式的行为相同。语句被放弃,表保持不变。如果语句插入或修改多行,并且坏值出现在第2或后面的行,结果取决于启用了哪个严格选项:

  对于strict_all_tables,mysql返回错误并忽视剩余的行。但是,在这种情况下,前面的行已经被插入或更新。这说明你可以部分更新,这可能不是你想要的。要避免这点,最好使用单行语句,因为这样可以不更改表即可以放弃。对于strict_trans_tables,mysql将非法值转换为最接近该列的合法值并插入调整后的值。如果值丢失,mysql在列中插入隐式 默认值。在任何情况下,mysql都会生成警告而不是给出错误并继续执行语句。

  其他模式还有:

  allow_invalid_dates:不完全对日期合法性作检查,只检查月份是否在1~12,日期是否在1~31之间;仅对date和datetime有效,而对timestamp无效,因为timestamp总要求一个合法的输入。

  ansi_quotes:启用后,不能用双引号来引用字符串,因为"(双引号)将被解释为标识符

  error_for_division_by_zero:启用后,在insert或update过程中,若数据被零除(或mod(x,0),则产生错误,若未启用,则产生警告,数据被零除时系统返回null。

  high_not_precedence:启用后,可获得以前旧版本的优先级:

  no_auto_create_user:禁止grant创建密码为空的用户。

  no_auto_value_on_zero:在自增长的列中插入0或null将不会是下一个自增长值。

  no_backslash_escapes:反斜杠"\"作为普通字符而非转义字符

  no_dir_in_create:在创建表时忽略所有index directory和data directory的选项。

  no_engine_substitution:启用后,若需要的存储引擎被禁用或未编译,则抛出错误;未启用时将用默认的存储引擎代替,并抛出一个异常。

  no_unsigned_substraction:启用后,两个unsigned类型相减返回signed类型。

  no_zero_date:启用后,不允许插入“0000-00-00 00:00:00”形如此类的零日期,这将抛出一个错误,若未启用,则可插入但仅会抛出一个警告。

  no_zero_in_date:启用后,不允许月份和日期为零,和 no_zero_date一起启用,如“1999-01-00”将抛出错误而非警告。若单独启用本项,则会抛出warning,然后插入如“0000-00-00 00:00:00”。

  only_full_group_by:对于group by聚合操作,若select中的列没有在group by中出现,那么这句sql是不合法的。

  pad_char_to_full_length:启用后,对于char类型将不会截断空洞数据;

  pipes_as_concat:将"||"视为连接操作符而非“或运算符”。

  real_as_float:将real视为float的同义词而非double的同义词。

  组合选项:

  ·ansi:

  real_as_float、pipes_as_concat、ansi_quotes、ignore_space、ansi

  ·oracle:

  pipes_as_concat、ansi_quotes、ignore_space、no_key_options、no_table_options、no_field_options、no_auto_create_user、oracle

  ·traditional:

  strict_trans_tables、strict_all_tables、no_zero_in_date、no_zero_date、error_for_division_by_zero、no_auto_create_user、no_engine_substitution、traditional

  ·mssql:

  pipes_as_concat、ansi_quotes、ignore_space、mssql、no_key_options、no_table_options、no_field_options、mssql

  ·db2:

  pipes_as_concat、ansi_quotes、ignore_space、no_key_options、no_table_options、no_field_options、db2

  ·mysql323:

  high_not_precedence、mysql323

  ·mysql40:

  high_not_precedence、mysql40

  ·maxdb:

  pipes_as_concat、ansi_quotes、ignore_space、no_key_options、no_table_options、no_field_options、no_auto_create_user、maxdb

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。