> 백엔드 개발 > PHP 튜토리얼 > [Mysql] Select 不到,Insert出错的问题,字段编码问题

[Mysql] Select 不到,Insert出错的问题,字段编码问题

WBOY
풀어 주다: 2016-06-06 20:49:34
원래의
1138명이 탐색했습니다.

Mysql 5.5 表结构为:

<code>CREATE TABLE `account` (
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
</code>
로그인 후 복사
로그인 후 복사

name 字段目前的编码:

<code>CharacterSet:gbk
Collation:gbk_chinese_ci
</code>
로그인 후 복사
로그인 후 복사

目前我的程序逻辑为:

首先:

<code>select * from `account` where `name`=?
</code>
로그인 후 복사
로그인 후 복사

如果返回空,则插入该name:

<code>insert into `account` (`name`) values(?)
</code>
로그인 후 복사
로그인 후 복사

现在在我后台有几个报错记录:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '积分' for key 'PRIMARY'

(请忽略name为乱码,这可能是我输出记录文本导致的)

我的问题是,为什么我明明先select了该name,没有我才会insert,还会导致这个异常?

这是否跟我设置了name字段为gbk编码有关?有没相关参考文章可以提供给我看下?

应该将该字段编码设置为什么来避免这个问题?

BTW:使用ignore参数当然可以忽略该异常,但我主要想知道为什么之前select无法获取,Insert却出错

回复内容:

Mysql 5.5 表结构为:

<code>CREATE TABLE `account` (
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
</code>
로그인 후 복사
로그인 후 복사

name 字段目前的编码:

<code>CharacterSet:gbk
Collation:gbk_chinese_ci
</code>
로그인 후 복사
로그인 후 복사

目前我的程序逻辑为:

首先:

<code>select * from `account` where `name`=?
</code>
로그인 후 복사
로그인 후 복사

如果返回空,则插入该name:

<code>insert into `account` (`name`) values(?)
</code>
로그인 후 복사
로그인 후 복사

现在在我后台有几个报错记录:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry '积分' for key 'PRIMARY'

(请忽略name为乱码,这可能是我输出记录文本导致的)

我的问题是,为什么我明明先select了该name,没有我才会insert,还会导致这个异常?

这是否跟我设置了name字段为gbk编码有关?有没相关参考文章可以提供给我看下?

应该将该字段编码设置为什么来避免这个问题?

BTW:使用ignore参数当然可以忽略该异常,但我主要想知道为什么之前select无法获取,Insert却出错

字符编码问题请高人来解答。

我只说点别的。

在高并发的情况下,你这两次操作的结果是不确定的,是不安全的。

使用如下的原子操作更安全一些。

<code>INSERT INTO `table` (`id`, `name`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`);
</code>
로그인 후 복사

或者

<code>INSERT IGNORE INTO `table` (`id`, `name`) VALUES (?, ?)
</code>
로그인 후 복사

个人认为这应该不是编码问题, 而是象 @HJin.me 所说, 是一个并发问题. 即session1 在select 得到empty set后; session2 去insert了一个相同的name; 此时session1去 insert, 则得到 duplicated.

mysql事务默认的隔离级别是repeated read, 不会防止上面的情况, 实验一把.

<code>session1:  start transaction;
session2:  start transaction;
session1:  select * from account where name='11'; //empty set
session2:  insert into account values('11');
session2:  commit;
session1:  insert into account values('11'); // duplicate key
</code>
로그인 후 복사
관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿