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.