mysql - 如何使用 MySQL 禁止 2 个用户在 Web 应用程序中编辑相同的数据(如果可能,使用 CodeIgniter)
问题描述
我在开发环境中使用 CodeIgniter 3 和 MariaDB 5.0(但在 prod 环境中使用 MySQL 5.6)。
我创建了一个 Web 应用程序,并实现了一个验证链来接受用户请求。
例如:
User A asked for something
The manager validate
The deputy validate
The commission validate
The accounting department validate
The request is accepted
这些验证在数据库中的几个表中注册。
我使用 SQL 事务通过 CodeIgniter 的函数和 CRUD 模型正确更新/插入数据,例如:
$this->db->trans_start();
$this->my_model->create($data);
$another_data = $this->second_model->read($second_data);
$this->another_model->create($another_data);
$this->db->trans_complete();
但是现在,我必须对总经理执行新规则。他有能力随时进行验证,而这种验证打破了验证链,因为它算作每个人都经过验证。
这种情况可能是一个例子:
User A asked for something
The manager validate
The general manager validate
The request is accepted
我不确定如何实现这一点,因为我意识到 2 个用户(例如总经理和副手)可以咨询同一个请求,一个拒绝,另一个验证,并且数据不再一致。
交易是否足够好?喜欢:
// User A asked for something
// The manager validate
// The deputy consult the request
// The manager consult the request
// The deputy validate:
$this->db->trans_start();
// check if already validated by the general manager
if ($this->model->read($data)) {
$this->db->trans_complete();
// redirection to a warning page
}
else {
$this->my_model->create($my_data);
}
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE)
// redirection to another warning page
// The general manager wants to refuse at the same time but the deputy's transaction started first, so he's redirected to a warning page
$this->db->trans_start();
// check if already validated by anyone
if ($this->model->read($data)) {
$this->db->trans_complete();
// redirection to a warning page
}
else {
$this->my_model->create($my_data);
}
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE)
// redirection to another warning page
// The validation chain continues after the deputy's validation
我想到了 LOCK TABLE 来禁止用户在其他人咨询相同请求时访问验证页面。但是TRANSACTION
并且LOCK TABLE
很难实现,因为它可以触发隐式提交,而且我没有足够的习惯来做到这一点。
我读到START TRANSACTION READ WRITE
这可能是一个更好的解决方案,但我没有完全理解,我不确定如何正确实施。
任何人都可以帮助我实施好的策略,如果可能的话,如果需要的话使用这些 SQL 函数的方法?
解决方案
我找到了解决方案,我FOR UPDATE
在查询之后使用了,这里是:
// the query for my results
private model_function_for_query() {
$this->db->select('my_select');
$this->db->from('my_table');
$this->db->where('my_where_clause');
return $this->db->get_compiled_select();
}
// the function to apply the FOR UPDATE on the query
public model_function() {
$query = $this->model_function_for_query();
$result = $this->db->query($query.' FOR UPDATE');
return $result->row();
}
在我的控制器中:
// start the transaction
$this->db->trans_start();
// do the query, locking tables
$data = $this->my_model->model_function();
// check if the data has not changed
...
// if not, do the data treatment, else redirect to the warning page
...
// close the transaction
$this->db->trans_complete();
// check if the transaction failed, and do the stuff
if ($this->db->trans_status() === FALSE)
...
else
...
推荐阅读
- javascript - “mysql”数据库不支持“User.repositories”中的数据类型“Array”
- linux - 为什么这个脚本没有杀死 Docker 后台进程?
- php - 创建自定义帖子类型后的 Wordpress 错误
- c# - 如何在 C# 中获取 Comprehend Medical Job Request 的状态
- java - Android dateFormat.parse(date) 我发送 01/03/2021 它显示 sun dec 27 00:00:00 GMT-05:00 2020
- rust - 为什么即使在本地安装后,rust 也无法为 openssl-sys v0.9.60 构建命令?
- react-native - 更改 react-native-screens 导航标题的高度
- flutter - 具有自定义类的列表和列表上的操作
- react-native - 世博会构建:TypeError:无法将未定义或空值转换为对象
- java - ExampleMatcher 配置用于查找具有空值的多个字段