简体   繁体   English

Yii2 唯一验证器在插入如此之快时不起作用

[英]Yii2 Unique Validator not working when insert so fast

I am using ActiveRecord model to save data.我正在使用 ActiveRecord 模型来保存数据。

Unique Validator works very perfect. Unique Validator工作得非常完美。 But when i insert data so fast, it no longer works perfectly.但是当我如此快速地插入数据时,它不再完美地工作。 In some request i get error that it can not catch by Yii.在某些请求中,我收到 Yii 无法捕获的错误。

Integrity constraint violation – yii\\db\\IntegrityException SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '***'...违反完整性约束– yii\\db\\IntegrityException SQLSTATE[23000]: 违反完整性约束:1062 重复条目 '***'...

Does we have any solution to handle this problem without adding another service ?我们是否有任何解决方案可以在不添加其他服务的情况下处理此问题?

Thanks !谢谢 !

Summing up in the comments...在评论中总结...

Most probably what you need is to lock table manually before validation and release lock after it.您最有可能需要的是在验证之前手动锁定表并在之后释放锁定。 Yii2 provides optimistic locks mechanism but it is not suitable for your case . Yii2 提供了乐观锁机制,但它不适合您的情况 Optimistic locks are supported only inside update and delete methods:乐观锁仅在 update 和 delete 方法中受支持:

Optimistic locking is only supported when you update or delete an existing row of data using yii\\db\\ActiveRecord::update() or yii\\db\\ActiveRecord::delete(), respectively.仅当您分别使用 yii\\db\\ActiveRecord::update() 或 yii\\db\\ActiveRecord::delete() 更新或删除现有数据行时,才支持乐观锁定。

Moreover what does optimistic lock is just raise exception when update fails due conflict (no actual table locking).此外,乐观锁只是在更新因冲突而失败时引发异常(没有实际的表锁定)。

The solution will depends on your DB engine.解决方案将取决于您的数据库引擎。 Yii2 provides mutex mechanism for manual locking. Yii2 提供了手动锁定的互斥机制。 Out of the box Yii2 supported Mysql and Postgres.开箱即用的 Yii2 支持 Mysql 和 Postgres。 See components description at following pages of Yii2 manual :请参阅 Yii2 手册以下页面的组件说明:

So, after you configured your mutex in config (example for pgsql from official guide):因此,在配置中配置互斥锁之后(来自官方指南的 pgsql 示例):

[
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'pgsql:host=127.0.0.1;dbname=demo',
        ]
        'mutex' => [
            'class' => 'yii\mutex\PgsqlMutex',
        ],
    ],
]

you'll need to do something like that你需要做这样的事情

\Yii::$app->mutex->acquireLock($lockingObject);

// validate uniqueness and save

\Yii::$app->mutex->releaseLock($lockingObject);

Or , for sure you can do it manually using SQL syntax of your RDBMS.或者,您可以使用 RDBMS 的 SQL 语法手动执行此操作。

MySQL : MySQL

SELECT GET_LOCK('tablename',10);
SELECT RELEASE_LOCK('tablename');

Pqsql : 查询语句

LOCK TABLE tablename IN SHARE ROW EXCLUSIVE MODE;

Be aware that Pgsql lock works only inside transaction.请注意,Pgsql 锁仅在事务内部起作用。

  • Unique Validator not work in this case Unique Validator在这种情况下不起作用

My solution for this problem ( prevent duplicate insert ):我对这个问题的解决方案(防止重复插入):

  • I use MySQL UNIQUE Index and INSERT IGNORE to ignore new record if exists.我使用MySQL UNIQUE IndexINSERT IGNORE来忽略新记录(如果存在)。 It easy to implement.它易于实施。 And It work very fast.它的工作速度非常快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM