表结构如下,在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);  /* 建表语句 */
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;

解决方案 »

  1.   

    锁表??
    但是goods表进行insert操作的时候,别的用户也经常对这3个表进行SELECT和UPDATE操作哦...
    这样不就会导致其他用户的操作变慢了??BTW,锁行的关键字是什么??
      

  2.   

    但是goods表进行insert操作的时候,别的用户也经常对这3个表进行SELECT和UPDATE操作哦...
    这样不就会导致其他用户的操作变慢了??

    那没办法。加锁和冲突是难免的。程序设计者需要在两者间平衡。BTW,锁行的关键字是什么??
    由MYSQL自行决定。可以参考文档中的锁相关介绍。
    MySQL官方文档 http://dev.mysql.com/doc/refman/5.1/zh/index.html
      

  3.   

    由MySQL自行决定??
    是说我依然使用LOCK TABLE关键字
    然后MySQL会根据我当前的数据库引擎和所进行的操作来判断进行锁表、锁页或是锁行??
      

  4.   

    对于InnoDB和BDB表,如果你用LOCK TABLES显式锁定表,MySQL只使用表锁定。对于这些表类型,我们建议你根本不要使用LOCK TABLES,因为InnoDB使用自动行级锁定而BDB使用页级锁定来保证事务隔离。
    =======================================================
    即是说连LOCK TABLES都不必,InnoDB数据库引擎会自动进行锁行??
    我上面的情况下它会自动进行锁行吗??
      

  5.   

    即是说连LOCK TABLES都不必,InnoDB数据库引擎会自动进行锁行??
    建议看一下手册中在哪些情况下会锁表。 比如事务中。 那么事务是否开启了?。
      

  6.   

    我对我的数据库进行测试了...
    在使用事务的情况下
    客户端1开始插入数据后,客户端2如果只是进行SELECT操作的话,则会出现排队现象
    但是...我为了查看锁状态,运行SHOW STATUS LIKE 'Table%';
    运行了3次后,最后发现一条数据都没插入....
    如果此时客户端2进行UPDATE操作的话(UPDATE px表),则插入失败在不使用事务的情况下
    客户端1开始插入数据后,客户端2进行SELECT操作,没出现排队现象
    如果插入过程中运行SHOW STATUS LIKE 'Table%';
    还是会导致数据插入失败...
    此时如果客户端2进行UPDATE操作(依然是px表),可以正常UPDATE
    现在想通过在INSERT goods表的时候,先将px和spec表中的isdel设置为1,这样别的用户如果是在插入后才想查看px或spec的相应数据时,则无法显示(已经被假删除了)
    如果用户是在插入操作前就已经在查看px或spec数据的话,则在UPDATE或INSERT操作前进行判断,判断此时px和spec的isdel字段是否为1,如果为1则返回错误提示。
    判断isdel字段只需要进行select操作,所以不管是否开启事务应该都不会影响到最终结果不知道这样是否行得通...