常见问题
LyMySQLCore 启动失败怎么办?
先检查控制台中的 MySQLLink -> jdbc:mysql://...,确认以下信息是否正确:
| 检查项 | 对应配置 | 说明 |
|---|---|---|
| 数据库地址 | mysql.ip | MySQL 服务器的 IP 地址或可解析域名 |
| 数据库端口 | mysql.port | 默认值为 3306 |
| 数据库名称 | mysql.databasename | 指定的数据库需要已经存在 |
| 数据库账号 | mysql.username | 用于建立连接和操作数据表 |
| 数据库密码 | mysql.password | 确认密码与账号匹配 |
| 连接参数 | mysql.link | 会直接拼接到 JDBC 地址末尾 |
正常启动时,控制台会依次出现数据库连接成功和插件初始化成功的信息。
如果出现 数据库连接失败 或 初始化失败,插件启动失败,继续检查:
- MySQL 服务是否正在运行。
- 数据库端口是否已开放。
- 服务器是否能够访问 MySQL 所在地址。
- 数据库账号是否允许从当前服务器地址登录。
- 配置中的数据库是否已经创建。
- 数据库账号是否具备建表和读写权限。
初始化失败后,LyMySQLCore 会禁用自身。所有依赖 LyMySQLCore 进行 MySQL 存储、玩家数据加载或保存的功能都不会生效。
数据库需要提前创建吗?
需要提前创建配置中 mysql.databasename 指定的数据库。LyMySQLCore 只负责在该数据库内创建自身需要的数据表,不会创建数据库本身。
首次成功连接后,插件会自动创建以下数据表:
| 数据表 | 用途 |
|---|---|
lymysqlcore_lock | 记录玩家当前持有的数据锁、所在服务器和锁更新时间 |
lymysqlcore_playerlog | 记录已发现玩家的名称和 UUID |
这两张基础表不需要手动创建。数据库账号至少需要能够连接数据库,并执行建表、查询、插入和更新操作。
其他插件使用的业务数据表是否自动创建,由对应插件自身决定。
为什么数据库连接成功后仍然初始化失败?
数据库连接成功只代表账号能够建立连接。插件启动时还会创建 lymysqlcore_lock 和 lymysqlcore_playerlog。
如果账号没有建表权限,或者数据库不支持相关建表语句,后续初始化仍会失败并禁用插件。应检查控制台中的异常信息以及数据库账号权限。
玩家进服后为什么会短暂失明并且无法操作?
这是玩家数据加载期间的保护流程,不是异常。
玩家进入服务器后,LyMySQLCore 会先等待并获取该玩家的数据锁,再异步执行已注册的数据加载逻辑。数据没有完成加载前,插件会给予玩家短暂的失明效果,并限制以下操作:
- 移动。
- 丢弃物品。
- 与方块或实体交互。
- 打开和点击背包。
- 发送聊天消息。
- 主动攻击实体。
移动时,玩家会被限制在刚进入服务器时的位置。这样可以避免玩家数据尚未读取完成,就提前操作依赖插件的物品、菜单或其他功能。
数据加载完成并经过 join-load-delay 设置的延迟后,插件会在主线程触发 MySQLSafePlayerLoadEvent,随后解除加载状态和失明效果。
join-load-delay 应该如何调整?
join-load-delay 的单位是 tick,默认值为 20。
该配置控制数据供应器完成异步加载后,到触发玩家加载事件并解除保护之间的延迟。按照正常服务器运行速度,20 tick 约为 1 秒,但实际时间会受到服务器卡顿影响。
如果玩家数据已经读取完成,但依赖插件仍需要短暂等待其他初始化流程,可以适当提高该值。设置过大则会让玩家在进服后等待更久。
修改后应完整重启服务器,不建议使用服务器热重载。
玩家为什么提示“数据加载失败,请稍后再试”?
出现该提示通常有两类原因:
- 玩家数据加载过程抛出异常。
- 玩家在其他服务器上的有效数据锁长时间没有释放。
加载过程抛出异常时,插件会记录严重错误、释放当前服务器取得的数据锁,并将在线玩家踢出,防止玩家在数据不完整的状态下继续游戏。
如果是其他服务器仍持有数据锁,插件会持续尝试获取。加载任务每 2 tick 检查一次,累计尝试达到 100 次后会终止本次登录流程。正常运行速度下,这一过程大约为 10 秒。
排查时应查看该玩家登录期间的完整控制台异常,不能只看最终踢出提示。
玩家卡在加载状态时应该检查什么?
按以下顺序检查:
- 确认所有相关服务器都连接到了预期的同一个数据库。
- 检查其他服务器上是否仍有同名玩家在线。
- 检查其他服务器是否异常崩溃,导致数据锁没有正常释放。
- 查看
lymysqlcore_lock中该玩家对应的server和lock_time。 - 查看依赖插件的数据加载逻辑是否抛出异常或长时间阻塞。
LyMySQLCore 将 61 秒以内、且服务器标识不是 @unlock 的记录视为有效锁。正常在线玩家的数据锁每 30 秒更新一次。旧锁超过有效时间后,不会继续阻止其他服务器获取该玩家的数据锁。
不要在玩家仍在线或服务器仍在保存数据时手动修改锁记录,否则可能造成同一玩家的数据被多个服务器同时读取和覆盖。
多个服务器共用数据库需要注意什么?
所有需要共享玩家数据的服务器必须安装 LyMySQLCore,并成功连接到同一个数据库。只有数据库连接和插件初始化都成功后,相关 MySQL 存储功能才会生效。
LyMySQLCore 使用以下内容组成服务器标识:
text
Bukkit 服务器名称-服务器端口例如服务器名称为 Lobby、端口为 25565 时,服务器标识为 Lobby-25565。
多服环境需要注意:
- 每个服务器实例应使用可区分的 Bukkit 服务器名称或端口。
- 不要让两个同时运行的实例使用完全相同的服务器名称和端口组合。
- 所有共享数据的服务器应使用同一套数据库表。
- 不同网络不应误连到同一个正式数据库,除非确实需要共享玩家数据。
- 服务器异常关闭后,旧锁可能在短时间内继续有效。
玩家正常离服或被踢出时会保存数据吗?
玩家正常退出或被踢出时,如果玩家已经完成数据加载并持有当前服务器的数据锁,LyMySQLCore 会执行已注册的数据保存逻辑,然后触发 MySQLSafePlayerSaveEvent,最后释放数据锁并清理玩家状态。
保存流程会避免对同一玩家重复执行。以下情况不会执行正常保存:
- 玩家数据仍在加载。
- 玩家没有持有当前服务器的数据锁。
- 玩家已经进入离服保存流程。
- 玩家加载失败。
依赖插件仍应保证自己的保存逻辑能够正确处理玩家离服与服务器关闭场景。
执行 stop 或 restart 时会发生什么?
LyMySQLCore 会监听控制台执行的 stop 和 restart:
- 将服务器标记为正在关闭或重启。
- 保存当前在线且已经加载完成的玩家数据。
- 释放对应的数据锁。
- 将在线玩家踢出服务器。
- 拒绝新的玩家登录。
插件禁用时,还会检查当前服务器是否仍有 61 秒以内的有效玩家锁。最多等待约 10 次、每次 1 秒,然后继续关闭流程。
如果其他插件需要通过 LyMySQLCore 保存数据,应确保保存逻辑能够在关闭流程中正常完成,不要在事件中执行无法结束的阻塞操作。
插件是否会定时保存在线玩家数据?
会。循环保存任务每 20 秒执行一次,并跳过以下玩家:
- 仍处于数据加载或加载失败状态的玩家。
- 已经离线的玩家。
已注册的数据供应器会分散执行循环保存,避免所有供应器始终在同一时刻集中写入。MySQLSafePlayerCycleSaveEvent 会在主线程中触发。
循环保存不能替代离服保存。依赖插件仍需正确处理玩家保存事件和服务器关闭时的数据保存。
lymysqlcore_playerlog 有什么作用?
玩家进入服务器时,LyMySQLCore 会异步检查 lymysqlcore_playerlog。如果表中没有该玩家名称,就会记录玩家名称和 UUID,并在控制台提示发现新玩家。
该表用于保存插件发现过的玩家身份记录,不是玩家业务数据表,也不代替其他插件自己的数据表。
当前逻辑只会在玩家名称不存在时插入记录,不会主动更新已有名称对应的数据。
修改数据库配置后可以重载吗?
不建议,也没有可确认的插件重载命令。
数据库连接池、基础数据表、监听器和定时任务都在插件启动时初始化。修改以下配置后,应完整重启服务器:
mysql.ipmysql.portmysql.databasenamemysql.usernamemysql.passwordmysql.linkjoin-load-delay
不要依赖 Bukkit 或 Paper 的热重载功能重新建立数据库连接,以免出现旧连接、重复任务或玩家锁状态异常。
LyMySQLCore 提供管理命令或权限吗?
项目中的 plugin.yml 没有声明玩家命令、管理命令或权限节点。
数据库配置、连接状态和异常需要通过配置文件、服务器控制台和数据库管理工具检查。不要使用未经项目文件确认的命令或权限节点。
依赖插件的 MySQL 功能为什么没有生效?
先确认以下条件全部满足:
- 服务器已经安装 LyMySQLCore。
- LyMySQLCore 已成功连接 MySQL。
- 控制台出现
初始化成功,插件启动成功。 - LyMySQLCore 没有在启动过程中被禁用。
- 依赖插件已正确加载,并接入 LyMySQLCore 的数据供应器或玩家数据事件。
- 玩家已经完成数据加载,没有处于受保护状态。
只安装业务插件但未安装 LyMySQLCore,或者 LyMySQLCore 数据库连接失败时,所有依赖其 MySQL 存储和安全读写流程的功能都不会生效。
一个数据供应器名称可以注册多次吗?
不可以。LyMySQLCore 会根据 MySQLSupplier#getName() 返回的名称判断供应器是否已经存在。
重复注册同名供应器会直接抛出异常:
text
MySQLSupplier <名称> already exists!开发者应为每个供应器使用唯一且稳定的名称。卸载或替换供应器时,可以按名称或供应器实例从 MySQLSupplierManager 中删除原注册项。
数据加载和保存按照什么顺序执行?
已注册的数据供应器会按照以下优先级顺序执行:
| 顺序 | 优先级 |
|---|---|
| 1 | LOWEST |
| 2 | LOW |
| 3 | NORMAL |
| 4 | HIGH |
| 5 | HIGHEST |
| 6 | MONITOR |
未指定优先级时,供应器使用 NORMAL。
同一优先级下的供应器存储在并发集合中,项目没有保证它们之间的固定执行顺序。如果两个供应器存在先后依赖,应使用不同优先级明确排序,不要依赖注册顺序。
数据供应器加载或保存时报错会怎样?
供应器的加载、保存或循环保存方法抛出异常时,LyMySQLCore 会将异常包装为运行时异常,并在信息中包含玩家名称和供应器名称。
玩家加载阶段发生异常时,本次登录流程会被终止,数据锁会被释放,在线玩家会收到 数据加载失败,请稍后再试 并被踢出。
普通离服保存和循环保存中的异常也会影响当前保存流程。开发者应在供应器内部正确处理数据库资源和可预期异常,并根据控制台中的供应器名称定位问题。
支持哪些服务端和 Java 版本?
项目可以确认的信息如下:
| 项目 | 项目文件中的信息 |
|---|---|
| Java 编译目标 | Java 8 |
| 服务端 API 编译目标 | Paper API 1.16.5-R0.1-SNAPSHOT |
| 插件版本 | 1.0.5 |
这表示项目以 Java 8 和 Paper 1.16.5 API 作为编译目标,不代表项目文件已经确认所有更高或更低 Minecraft 版本均兼容。跨版本使用前应在测试服务器验证数据库连接、玩家登录、跨服切换、离服保存和关服保存流程。