我有一个将用户数据发送到云端的客户端-服务器应用程序 (Amazon EC2 + RDS + S3)。
- 每个用户都可以有多个设备同时连接到云端并发送数据
- 安装在每台设备上的客户端应用程序是多线程的,最终会同时上传多个数据片段。
我想可靠地跟踪在这种情况下使用的磁盘使用情况,我想知道在这种情况下如何做到这一点?
到目前为止我有两个想法,但我什至不确定它们是否正确:
选项 1:向 mysql 表添加触发器?即。
CREATE TRIGGER DiskUsage AFTER UPDATE OF Fully_Updated_File_Flag ON Files
BEGIN
for each row
begin
UPDATE Users SET SpaceUsed = SpaceUsed + new.Size WHERE (new.Fully_Updated_File_Flag = 1) And UserID=
end
END;
如果我选择使用触发器,我应该如何动态注入(inject)用户 ID?
选项 2:通过 PHP 更新 mysql 表?即。
<?php
SendFileToS3($file_name);
mysql_query('UPDATE Stats SET Value = Value + ' . filesize($file_name) . ' WHERE user_id=' . $user_id);
?>
如果两个实例试图更新同一条记录怎么办? (我正在使用 Mysql 5.5.27-log/MyISAM),这仍然有效吗?
注意#1 虽然我还没有发布我的应用程序,但我仍然需要一些可以很好扩展的东西。即使这意味着要一起更改数据库引擎。
注意 #2 与数据库相关的代码封装在模块化函数中(即 InsertIntoDB()、UpdateDB() 和 DeleteFromDB())。此外,所有这些例程都依赖于带有事件记录类的 CodeIgniter 2.1。
这就是说,如果我必须这样做,我总是可以进行切换(尽管我想避免这种情况)
最佳答案
您应该使用 MySQL 触发器而不是 PHP 代码,并且您必须将相关的 user_id
存储到 diskusage
表中。
I use
InnoDB
engine because of theCONSTRAINT
. You can also useMyISAM
, but you should remove theCONSTRAINT
.
备注
我会使用 InnoDB
因为 Transactions 和(这里更重要)Row-Locking。
表结构 (InnoDB)
-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(10) NOT NULL DEFAULT '',
`SpaceUsed` BIGINT(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `diskusage`
-- ----------------------------
DROP TABLE IF EXISTS `diskusage`;
CREATE TABLE `diskusage` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`Filename` VARCHAR(50) NOT NULL DEFAULT '',
`Size` BIGINT(20) NOT NULL,
`user_id` INT(11) UNSIGNED DEFAULT NULL,
`Fully_Updated_File_Flag` TINYINT(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_diskusage_user` (`user_id`),
CONSTRAINT `fk_diskusage_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=INNODB DEFAULT CHARSET=utf8;
表结构(MyISAM)
-- ----------------------------
-- Table structure for `users`
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(10) NOT NULL DEFAULT '',
`SpaceUsed` BIGINT(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `diskusage`
-- ----------------------------
DROP TABLE IF EXISTS `diskusage`;
CREATE TABLE `diskusage` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`Filename` VARCHAR(50) NOT NULL DEFAULT '',
`Size` BIGINT(20) NOT NULL,
`user_id` INT(11) UNSIGNED DEFAULT NULL,
`Fully_Updated_File_Flag` TINYINT(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_diskusage_user` (`user_id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
这就是全部,以及表 diskusage
上的一些触发器。
插入触发器
-- ----------------------------
-- AFTER INSERT TRIGGER for `diskusage`
-- ----------------------------
delimiter ;;
CREATE TRIGGER `diskusage_after_insert` AFTER INSERT ON `diskusage` FOR EACH ROW BEGIN
IF NEW.Fully_Updated_File_Flag = 1 THEN
UPDATE users
SET
SpaceUsed = SpaceUsed + NEW.Size
WHERE
id = NEW.user_id;
END IF;
END;
;;
delimiter ;
更新触发器
-- ----------------------------
-- AFTER UPDATE TRIGGER for `diskusage`
-- ----------------------------
delimiter ;;
CREATE TRIGGER `diskusage_after_update` AFTER UPDATE ON `diskusage` FOR EACH ROW BEGIN
-- same to DELETE TRIGGER
-- decrease SpaceUsed with OLD Size for OLD user
IF OLD.Fully_Updated_File_Flag = 1 THEN
UPDATE users
SET
SpaceUsed = SpaceUsed - OLD.Size
WHERE
id = OLD.user_id;
END IF;
-- same to INSERT TRIGGER
-- increase SpaceUsed with NEW Size for NEW user
IF NEW.Fully_Updated_File_Flag = 1 THEN
UPDATE users
SET
SpaceUsed = SpaceUsed + NEW.Size
WHERE
id = NEW.user_id;
END IF;
END;
;;
delimiter ;
删除触发器
-- ----------------------------
-- AFTER DELETE TRIGGER for `diskusage`
-- ----------------------------
delimiter ;;
CREATE TRIGGER `diskusage_after_delete` AFTER DELETE ON `diskusage` FOR EACH ROW BEGIN
IF OLD.Fully_Updated_File_Flag = 1 THEN
UPDATE users
SET
SpaceUsed = SpaceUsed - OLD.Size
WHERE
id = OLD.user_id;
END IF;
END;
;;
delimiter ;
关于php - 在 mysql MyISAM 表中同时更新计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14111487/