2009-11-12 47 views
0

我有一个包含ip地址部分InnoDB的交易帮助 - 然后选择是否未找到添加唯一行

TABLE `EndPoints`(
    `EndPointId` BIGINT(19) UNSIGNED NOT NULL AUTO_INCREMENT , 
    `IpPart1` TINYINT(3) UNSIGNED NOT NULL , 
    `IpPart2` TINYINT(3) UNSIGNED NOT NULL , 
    `IpPart3` TINYINT(3) UNSIGNED NOT NULL , 
    `IpPart4` TINYINT(3) UNSIGNED NOT NULL , 
    PRIMARY KEY (`EndPointId`)) 
ENGINE = InnoDB 

每个IpPart包含一个ip地址字节数组的字节一个MySQL表。 例如地址100.101.102.103
IpPart1 = 101;
IpPart2 = 102;
IpPart3 = 103;
IpPart4 = 104;


无论如何!

我要做到以下几点:

SELECT EndPointId FROM EndPoints WHERE 
    IpPart1 = @a AND 
    IpPart2 = @b AND 
    IpPart3 = @c AND 
    IpPart4 = @d; 

然后,如果未找到地址,将其添加

INSERT INTO EndPoints (IpPart1,IpPart2,IpPart3,IpPart4) 
    Values(@a,@b,@c,@d); 

使用MySQL的交易将如何确保只有每行添加一行IPAddress?

谢谢!

回答

0

那么你可能开始一个事务,做你引用的两个查询,然后COMMIT。但是,将一个UNIQUE键置于(IpPart1,IpPart2,IpPart3,IpPart4)上会不会更容易?

(通过这种方式将八位字节分隔出来真的有什么需要获得的东西吗?例如,你不想单独搜索和索引IpPart3,IPv4地址通常以字符串或简单整数形式存储通过inet_aton。IPv6地址是一个更多的工作,使用规范化的字符串或BINARY字符(16)。)

+0

谢谢bobince,是啊我知道这很奇怪,但我希望能够映射IP类等。你会去做交易吗?我想我必须做一个非锁定的选择。如果不存在,用IsolationLevel.Serializable(我认为锁定表)锁定表,然后再次执行选择! - 看看它是否刚刚插入,然后如果仍然不存在,请执行插入..提交...我在正确的轨道上? – divinci 2009-11-12 13:11:37

+0

由于查询是基于行存在的,所以你不能用简单的'SELECT FOR UPDATE'离开,但除了全表锁(通常要避免)之外还有其他方法。通过在复合IpParts索引上设置'UNIQUE'约束,它就像单独执行INSERT一样简单,然后捕获并忽略异常(如果它已经存在)。或者,使用MySQL特有的语法INSERT IGNORE。 – bobince 2009-11-12 17:43:04