日期:2014-05-16  浏览次数:20738 次

插入数据的时候,如何避免与之相关的表数据被更改?
表结构如下,在px和spec表中已经存在相关数据情况下,要插入数据到goods表中
如果要插入的数据非常多,那要如何避免此时用户对相应px和spec表中的数据进行修改呢?
假设插入的是10万条 pid=1,sid随机的数据,10万条数据要插入也得一段时间
如果此时有别的用户打开px.id=1的数据,并进行插入数据的话,那该如何限制让B的提交无效呢?
如果是A和B用户都打开px.id=1的数据,A用户先提交插入10万条数据,而在A提交后,B也提交,那又该如何限制让B无法插入呢?
INSERT INTO `goods`(`pid`,`sid`) VALUES
(1,1),(1,2),(1,2),(1,3),(1,3),(1,3);  

SQL code
/* 建表语句 */
DROP DATABASE IF EXISTS `testtest`;
CREATE DATABASE `testtest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `testtest`;

DROP TABLE IF EXISTS `px`;
CREATE TABLE IF NOT EXISTS `px` (
  `id` int(2) NOT NULL AUTO_INCREMENT,
  `desc` varchar(10) CHARACTER SET gbk DEFAULT NULL,
  `isdel` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(0:不删除|1:删除)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

DROP TABLE IF EXISTS `spec`;
CREATE TABLE IF NOT EXISTS `spec` (
  `id` int(2) NOT NULL AUTO_INCREMENT,
  `pid` int(2) NOT NULL,
  `isdel` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(0:不删除|1:删除)',
  PRIMARY KEY (`id`),
  KEY `pact_id` (`pid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

DROP TABLE IF EXISTS `goods`;
CREATE TABLE IF NOT EXISTS `goods` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `pid` int(2) NOT NULL,
  `sid` int(2) NOT NULL,
  `isdel` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(0:不删除|1:删除)',
  PRIMARY KEY (`id`),
  KEY `pid` (`pid`),
  KEY `sid` (`sid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

/* 添加约束 */
ALTER TABLE `goods`
  ADD CONSTRAINT `goods_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `px` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `goods_ibfk_2` FOREIGN KEY (`sid`) REFERENCES `spec` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `spec`
  ADD CONSTRAINT `spec_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `px` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;

/* 插入数据 */
INSERT INTO `px`(`isdel`) VALUES (0),(0),(0);
INSERT INTO `spec`(`pid`) VALUES (1),(1),(1),(2),(2),(3),(3);

/* 添加触发器 */
/* 更新px的isdel字段时,更新spec和goods的isdel字段 */
DELIMITER $$
CREATE TRIGGER `hidden_px` BEFORE UPDATE ON `px`
FOR EACH ROW
BEGIN
UPDATE `spec`,`goods`
SET `spec`.`isdel` = NEW.`isdel`,`goods`.`isdel` = NEW.`isdel`
WHERE NEW.`id` = `spec`.`pid` AND NEW.`id` = `goods`.`pid`;
END$$
DELIMITER ;
COMMIT;


------解决方案--------------------
LOCK TABLES
------解决方案--------------------
但是goods表进行insert操作的时候,别的用户也经常对这3个表进行SELECT和UPDATE操作哦...
这样不就会导致其他用户的操作变慢了??
那没办法。加锁和冲突是难免的。程序设计者需要在两者间平衡。

BTW,锁行的关键字是什么??
由MYSQL自行决定。

可以参考文档中的锁相关介绍。
MySQL官方文档 http://dev.mysql.com/doc/refman/5.1/zh/index.html
------解决方案--------------------
即是说连LOCK TABLES都不必,InnoDB数据库引擎会自动进行锁行??
建议看一下手册中在哪些情况下会锁表。 比如事务中。 那么事务是否开启了?。。。。