当插入速度如此之快时,Yii2 Unique Validator无法正常工作

时间:2016-07-21 03:03:53

标签: php yii yii2 yii2-validation yii-cactiverecord

我正在使用ActiveRecord模型来保存数据。

Unique Validator非常完美。但是当我如此快速地插入数据时,它就不再完美。在某些请求中,我得到Yii无法捕获的错误。

  

完整性约束违规 - yii \ db \ IntegrityException   SQLSTATE [23000]:完整性约束违规:1062重复条目   ' ***' ...

我们是否有任何解决方案来处理此问题而不添加其他服务?

谢谢!

2 个答案:

答案 0 :(得分:1)

总结评论......

您最需要的是在验证之前手动锁定表并在其之后释放锁定。 Yii2提供optimistic locks机制但它不适合您的情况。仅在更新和删除方法中支持乐观锁

  

只有在更新或删除时才支持乐观锁定   使用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语法手动执行此操作。

MySQL

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

Pqsql

LOCK TABLE tablename IN SHARE ROW EXCLUSIVE MODE;

请注意,Pgsql锁只能在事务内部工作。

答案 1 :(得分:0)

我解决这个问题的方法:

  • Unique Validator在这种情况下不起作用
  • 我使用INSERT IGNORE忽略新记录(如果存在)。它的工作非常快。