Um caso de acidente de produção do MySQL

fundo

O registro online relata um erro:

18:57:54.985 [http-nio-8082-exec-9] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'inserttime' cannot be null
### The error may exist in class path resource [mapping/VarMonitorMapper.xml]
### The error may involve com.aaa.dao.VarMonitorMapper.insert-Inline
### The error occurred while setting parameters
### SQL: insert into var_monitor (var_id, inserttime, insertby, updatetime, updateby) values (?, ?, ?, ?, ?)
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'inserttime' cannot be null
; Column 'inserttime' cannot be null; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'inserttime' cannot be null] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'inserttime' cannot be null

A declaração de construção de tabela correspondente:

inserttime timestamp default CURRENT_TIMESTAMP not null comment '插入时间',

análise

Resumo do problema:
A definição do campo inserttime no ambiente de teste e no ambiente de produção é a mesma: a inserttime timestamp default CURRENT_TIMESTAMP not null comment '插入时间'diferença está no número da versão.
ambiente de teste:

select version();
5.7.16

Ambiente de produção:

select version();
5.7.21-20-log

Traga palavras timestamp default CURRENT_TIMESTAMP- chave e Column 'inserttime' cannot be nullpesquise no Google. Encontre um caso MySQL .

ambiente de teste:

show variables like '%explicit_defaults_for_timestamp%';
explicit_defaults_for_timestamp=OFF

Ambiente de produção:

show variables like '%explicit_defaults_for_timestamp%';
explicit_defaults_for_timestamp=ON

A declaração de criação da tabela significa que ao inserir os dados, se os dados da hora de inserção estiverem vazios, será utilizada a hora padrão do sistema, razão pela qual o ambiente de teste não encontrou este problema.
No ambiente de produção, explicit_defaults_for_timestamp=ONse os dados de tempo de inserção estiverem vazios, um erro será relatado Column 'inserttime' cannot be null. Nota: Você pode inserir uma parte dos dados com o tempo de inserção nulo diretamente por meio do cliente, como o dataGrip.

Solução

  1. Modifique a configuração dos parâmetros de produção. Em primeiro lugar, não é recomendado. Em segundo lugar, não há autoridade de modificação. Você precisa entrar em contato com o DBA para executar (e convencê-los):
    set explicit_defaults_for_timestamp=OFF
  2. Mybatis usa insertSelective em vez de insert, é recomendado:
<insert id="insert" parameterType="com.aaa.model.VarMonitor">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        SELECT LAST_INSERT_ID()
    </selectKey>
    insert into var_monitor (var_id, inserttime, insertby, updatetime, updateby)
    values (#{varId,jdbcType=INTEGER}, #{inserttime,jdbcType=TIMESTAMP}, #{insertby,jdbcType=VARCHAR}, #{updatetime,jdbcType=TIMESTAMP}, #{updateby,jdbcType=VARCHAR})
</insert>

<insert id="insertSelective" parameterType="com.aaa.model.VarMonitor">
   <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
       SELECT LAST_INSERT_ID()
   </selectKey>
   insert into var_monitor
   <trim prefix="(" suffix=")" suffixOverrides=",">
       <if test="varId != null">
           var_id,
       </if>
       <if test="inserttime != null">
           inserttime,
       </if>
       <if test="insertby != null">
           insertby,
       </if>
       <if test="updatetime != null">
           updatetime,
       </if>
       <if test="updateby != null">
           updateby,
       </if>
   </trim>
   <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="varId != null">
           #{varId,jdbcType=INTEGER},
       </if>
       <if test="inserttime != null">
           #{inserttime,jdbcType=TIMESTAMP},
       </if>
       <if test="insertby != null">
           #{insertby,jdbcType=VARCHAR},
       </if>
       <if test="updatetime != null">
           #{updatetime,jdbcType=TIMESTAMP},
       </if>
       <if test="updateby != null">
           #{updateby,jdbcType=VARCHAR},
       </if>
   </trim>
</insert>

  1. Modifique as configurações do banco de dados, não é recomendado:
    alter table var_monitor modify column inserttime timestamp default CURRENT_TIMESTAMP null comment '插入时间';

referência

Um caso MySQL

Acho que você gosta

Origin blog.csdn.net/lonelymanontheway/article/details/108133879
Recomendado
Clasificación