我正在使用 ActiveRecord 模型来保存数据。
Unique Validator
工作非常完美。但是当我如此快速地插入数据时,它就不再完美了。在某些请求中,我得到了 Yii 无法捕获的错误。
完整性约束违规– yii\db\IntegrityException SQLSTATE[23000]: 完整性约束违规: 1062 Duplicate entry '***'...
我们有什么解决方案可以在不添加其他服务的情况下解决这个问题吗?
谢谢 !
我正在使用 ActiveRecord 模型来保存数据。
Unique Validator
工作非常完美。但是当我如此快速地插入数据时,它就不再完美了。在某些请求中,我得到了 Yii 无法捕获的错误。
完整性约束违规– yii\db\IntegrityException SQLSTATE[23000]: 完整性约束违规: 1062 Duplicate entry '***'...
我们有什么解决方案可以在不添加其他服务的情况下解决这个问题吗?
谢谢 !
总结在评论...
您最可能需要的是在验证之前手动锁定表并在验证之后释放锁定。Yii2 提供了乐观锁机制,但不适合您的情况。乐观锁仅在更新和删除方法中受支持:
仅当您分别使用 yii\db\ActiveRecord::update() 或 yii\db\ActiveRecord::delete() 更新或删除现有数据行时,才支持乐观锁定。
此外,乐观锁只是在更新因冲突失败时引发异常(没有实际的表锁定)。
解决方案将取决于您的数据库引擎。Yii2为手动锁定提供互斥机制。开箱即用 Yii2 支持 Mysql 和 Postgres。请参阅 Yii2 手册以下页面的组件描述:
因此,在配置中配置互斥锁后(官方指南中的 pgsql 示例):
[
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'pgsql:host=127.0.0.1;dbname=demo',
]
'mutex' => [
'class' => 'yii\mutex\PgsqlMutex',
],
],
]
你需要做这样的事情
\Yii::$app->mutex->acquireLock($lockingObject);
// validate uniqueness and save
\Yii::$app->mutex->releaseLock($lockingObject);
或者,您当然可以使用 RDBMS 的 SQL 语法手动完成。
SELECT GET_LOCK('tablename',10);
SELECT RELEASE_LOCK('tablename');
qsql:
LOCK TABLE tablename IN SHARE ROW EXCLUSIVE MODE;
请注意,Pgsql 锁仅在事务内部有效。
Unique Validator
在这种情况下不起作用我对这个问题的解决方案(防止重复插入):
MySQL UNIQUE Index
andINSERT IGNORE
忽略新记录。它易于实施。它工作得非常快。