TP ORM usage problem
Since the swoole is running in the resident memory + coroutine environment, when using the TP ORM, the TP ORM comes with a lot of static variables, and there will be problems. The specific analysis is as follows:
Non-co-resident resident memory mode
In synchronous, non-co-schedu mode, a worker only processes one request in one time, and will restart the process when it reaches max_request. It can barely operate sql, but the following static variables will have problems:
Think\Db static variable:
protected static $config = [];
//Database configuration, almost no impact
protected static $query;
//Query class name, no effect
protected static $queryMap = [
'mongo' => '\\think\\db\Mongo',
];
//Query class automatic mapping, no effect
public static $queryTimes = 0;
//Database query count
//Resident memory is the number of global queries
public static $executeTimes = 0;
//Number of executions
//Resident memory is actually the number of global executions
protected static $cacheHandler;
//Cache object, no effect
Think\Model static variable:
protected static $initialized = [];
//Initialized model.
//Original role: ensure that the init method in a model class is only executed once in a single request.
//Resident in memory: A model only executes this method on the first request, subsequent requests are no longer executed, and it is very likely to cause a bug.
protected static $readMaster;
//Whether to read data from the main library
//Almost no effect
Think\db\Connection static variable:
protected static $instance = [];
//PDO operation example
//Established connection management instance
//Coroutine mode, high concurrency may cause database operation bugs
protected static $event = [];
//Listening callback
//Original role: event callback set for the model
//Resident memory: As the running time increases, the running memory will continue to increase, and the event of one request increase will affect another request.
protected static $info = [];
// Data sheet information
// Almost no effect
protected static $log = [];
// Database log
// Original role: Log all log operations for a request
// Resident memory: As the database continues to operate, this variable will continue to increase, causing memory overflow
Think\db\Query static variable:
protected static $connections = [];
// Database Connection object
// Temporarily not found where to use
private static $event = [];
//Callback event
//Original role: set a callback event of its own under one request
//Resident in memory: an event that is added in one request will affect another request
private static $extend = [];
//Extended query method
//Almost no effect
private static $readMaster = [];
//Need to read the table of the main library
//Original role: set whether one or all models read data from the main library
//Resident memory: If a Query::readMaster() method is executed on a request, Query::$readMaster will not be released, which will affect other requests.
Think\Db\ModelEvent Static variable:
private static $event = [];
// Callback event
//Original role: event callback set for the model
//Resident memory: As the running time increases, the running memory will continue to increase, and the event of one request increase will affect another request.
protected static $observe = ['before_write', 'after_write', 'before_insert', 'after_insert', 'before_update', 'after_update', 'before_delete', 'after_delete', 'before_restore', 'after_restore'];
//Model event observation
//No effect
Coroutine resident memory mode
In the coroutine mode, multiple clients share a database connection, and database operation exceptions will occur. E.g:
- User A accesses service A, database opens transaction -> payment logic -> complete transaction
- User B accesses service B at the same time and inserts n data.
- User C accesses service A at the same time, the database opens the transaction->payment logic->logic error, rollback
In this logic, since both are sharing a database operation and are affected by coroutine switching, the database execution steps may become: User A database open transaction -> User B inserts n data -> User C opens transaction -> User A payment logic -> User C payment logic -> User C logic error, rollback transaction -> User A completes transaction When the database is executed like this, all database operations of users A, B, and C will be rolled back, but the front end may return success.
Similarly, due to the sharing of static variables, other callback events and other issues also exist.